home *** CD-ROM | disk | FTP | other *** search
/ .net 2002 March / DotNetMagazine-Issue107-Coverdisc-NET107-02-03-PCMac.bin / pc / PC Software / picks / HTTrack / httrack-3.22-3.exe / {app} / src / htscoremain.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-11-17  |  80.9 KB  |  2,209 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: httrack.c subroutines:                                 */
  34. /*       main routine (first called)                            */
  35. /* Author: Xavier Roche                                         */
  36. /* ------------------------------------------------------------ */
  37.  
  38. #include "htscoremain.h"
  39.  
  40. #include "htsglobal.h"
  41. #include "htscore.h"
  42. #include "htsdefines.h"
  43. #include "htsalias.h"
  44. #include "htswrap.h"
  45. #include "htsmodules.h"
  46.  
  47. #include <ctype.h>
  48. #if HTS_WIN
  49. #else
  50. #ifndef HTS_DO_NOT_USE_UID
  51. /* setuid */
  52. #include <pwd.h>
  53. #if HAVE_UNISTD_H
  54. #include <unistd.h>
  55. #endif
  56. #endif
  57. #endif
  58.  
  59. extern int exit_xh;          // sortir prÈmaturÈment
  60.  
  61. /* Resolver */
  62. extern int IPV6_resolver;
  63.  
  64.  
  65. // Add a command in the argc/argv
  66. #define cmdl_add(token,argc,argv,buff,ptr) \
  67.   argv[argc]=(buff+ptr); \
  68.   strcpybuff(argv[argc],token); \
  69.   ptr += (strlen(argv[argc])+2); \
  70.   argc++
  71.  
  72. // Insert a command in the argc/argv
  73. #define cmdl_ins(token,argc,argv,buff,ptr) \
  74.   { \
  75.   int i; \
  76.   for(i=argc;i>0;i--)\
  77.   argv[i]=argv[i-1];\
  78.   } \
  79.   argv[0]=(buff+ptr); \
  80.   strcpybuff(argv[0],token); \
  81.   ptr += (strlen(argv[0])+2); \
  82.   argc++
  83.  
  84. #define htsmain_free() do { if (url != NULL) { free(url); } } while(0)
  85.  
  86. #define ensureUrlCapacity(url, urlsize, size) do { \
  87.   if (urlsize < size || url == NULL) { \
  88.     urlsize = size; \
  89.     if (url == NULL) { \
  90.       url = (char*) malloct(urlsize); \
  91.       if (url != NULL) url[0]='\0'; \
  92.     } else { \
  93.       url = (char*) realloct(url, urlsize); \
  94.     } \
  95.     if (url == NULL) { \
  96.       HTS_PANIC_PRINTF("* memory exhausted"); \
  97.       htsmain_free(); \
  98.       return -1; \
  99.     } \
  100.   } \
  101. } while(0)
  102.  
  103. // Main, rÈcupËre les paramËtres et appelle le robot
  104. #if HTS_ANALYSTE
  105. HTSEXT_API int hts_main(int argc, char **argv) {
  106. #else
  107. int main(int argc, char **argv) {
  108. #endif
  109.   char* x_argv[999];      // Patch pour argv et argc: en cas de rÈcupÈration de ligne de commande
  110.   char* x_argvblk=NULL;   // (reprise ou update)
  111.   int   x_ptr=0;          // offset
  112.   /*
  113.   char* x_argv2[999];     // Patch pour config
  114.   char* x_argvblk2=NULL;
  115.   */
  116.   //
  117.   int argv_url=-1;           // ==0 : utiliser cache et doit.log
  118.   char* argv_firsturl=NULL;  // utilisÈ pour nommage par dÈfaut
  119.   char* url = NULL;          // URLS sÈparÈes par un espace
  120.   int   url_sz = 65535;
  121.   //char url[65536];         // URLS sÈparÈes par un espace
  122.   // the parametres
  123.   httrackp httrack;
  124.   int httrack_logmode=3;   // ONE log file
  125.   int recuperer=0;       // rÈcupÈrer un plantage (n'arrive jamais, ‡ supprimer)
  126. #if HTS_WIN
  127. #if HTS_ANALYSTE!=2
  128.   WORD   wVersionRequested; /* requested version WinSock API */ 
  129.   WSADATA wsadata;        /* Windows Sockets API data */
  130. #endif
  131. #else
  132. #ifndef HTS_DO_NOT_USE_UID
  133.   int switch_uid=-1,switch_gid=-1;      /* setuid/setgid */
  134. #endif
  135.   int switch_chroot=0;                  /* chroot ? */
  136. #endif
  137.   //
  138.   ensureUrlCapacity(url, url_sz, 65536);
  139.   //
  140.  
  141. #if HTS_ANALYSTE
  142.   // custom wrappers
  143.   hts_htmlcheck_init         = (t_hts_htmlcheck_init)           htswrap_read("init");
  144.   hts_htmlcheck_uninit       = (t_hts_htmlcheck_uninit)         htswrap_read("free");
  145.   hts_htmlcheck_start        = (t_hts_htmlcheck_start)          htswrap_read("start");
  146.   hts_htmlcheck_end          = (t_hts_htmlcheck_end)            htswrap_read("end");
  147.   hts_htmlcheck_chopt        = (t_hts_htmlcheck_chopt)          htswrap_read("change-options");
  148.   hts_htmlcheck              = (t_hts_htmlcheck)                htswrap_read("check-html");
  149.   hts_htmlcheck_query        = (t_hts_htmlcheck_query)          htswrap_read("query");
  150.   hts_htmlcheck_query2       = (t_hts_htmlcheck_query2)         htswrap_read("query2");
  151.   hts_htmlcheck_query3       = (t_hts_htmlcheck_query3)         htswrap_read("query3");
  152.   hts_htmlcheck_loop         = (t_hts_htmlcheck_loop)           htswrap_read("loop");
  153.   hts_htmlcheck_check        = (t_hts_htmlcheck_check)          htswrap_read("check-link");
  154.   hts_htmlcheck_pause        = (t_hts_htmlcheck_pause)          htswrap_read("pause");
  155.   hts_htmlcheck_filesave     = (t_hts_htmlcheck_filesave)       htswrap_read("save-file");
  156.   hts_htmlcheck_linkdetected = (t_hts_htmlcheck_linkdetected)   htswrap_read("link-detected");
  157.   hts_htmlcheck_xfrstatus    = (t_hts_htmlcheck_xfrstatus)      htswrap_read("transfer-status");
  158.   hts_htmlcheck_savename     = (t_hts_htmlcheck_savename)       htswrap_read("save-name");
  159. #endif
  160.  
  161.   // options par dÈfaut
  162.   memset(&httrack, 0, sizeof(httrackp));
  163.   httrack.wizard=2;   // wizard automatique
  164.   httrack.quiet=0;     // questions
  165.   //  
  166.   httrack.travel=0;   // mÍme adresse
  167.   httrack.depth=9999; // mirror total par dÈfaut
  168.   httrack.extdepth=0; // mais pas ‡ l'extÈrieur
  169.   httrack.seeker=1;   // down 
  170.   httrack.urlmode=2;  // relatif par dÈfaut
  171.   httrack.debug=0;    // pas de dÈbug en plus
  172.   httrack.getmode=3;  // linear scan
  173.   httrack.maxsite=-1; // taille max site (aucune)
  174.   httrack.maxfile_nonhtml=-1; // taille max fichier non html
  175.   httrack.maxfile_html=-1;    // idem pour html
  176.   httrack.maxsoc=8;     // nbre socket max
  177.   httrack.fragment=-1;  // pas de fragmentation
  178.   httrack.nearlink=0;   // ne pas prendre les liens non-html "adjacents"
  179.   httrack.makeindex=1;  // faire un index
  180.   httrack.kindex=0;     // index 'keyword'
  181.   httrack.delete_old=1; // effacer anciens fichiers
  182.   httrack.makestat=0;  // pas de fichier de stats
  183.   httrack.maketrack=0; // ni de tracking
  184.   httrack.timeout=120; // timeout par dÈfaut (2 minutes)
  185.   httrack.cache=1;     // cache prioritaire
  186.   httrack.shell=0;     // pas de shell par defaut
  187.   httrack.proxy.active=0;    // pas de proxy
  188.   httrack.user_agent_send=1; // envoyer un user-agent
  189.   strcpybuff(httrack.user_agent,"Mozilla/4.5 (compatible; HTTrack 3.0x; Windows 98)");
  190.   httrack.savename_83=0;     // noms longs par dÈfaut
  191.   httrack.savename_type=0;   // avec structure originale
  192.   httrack.parsejava=1;       // parser classes
  193.   httrack.hostcontrol=0;     // PAS de control host pour timeout et traffic jammer
  194.   httrack.retry=2;           // 2 retry par dÈfaut
  195.   httrack.errpage=1;         // copier ou gÈnÈrer une page d'erreur en cas d'erreur (404 etc.)
  196.   httrack.check_type=1;      // vÈrifier type si inconnu (cgi,asp..) SAUF / considÈrÈ comme html
  197.   httrack.all_in_cache=0;    // ne pas tout stocker en cache
  198.   httrack.robots=2;          // traiter les robots.txt
  199.   httrack.external=0;        // liens externes normaux
  200.   httrack.passprivacy=0;     // mots de passe dans les fichiers
  201.   httrack.includequery=1;    // include query-string par dÈfaut
  202.   httrack.mirror_first_page=0;  // pas mode mirror links
  203.   httrack.accept_cookie=1;   // gÈrer les cookies
  204.   httrack.cookie=NULL;
  205.   httrack.http10=0;          // laisser http/1.1
  206.   httrack.nocompression=0;   // pas de compression
  207.   httrack.tolerant=0;        // ne pas accepter content-length incorrect
  208.   httrack.parseall=1;        // tout parser (tags inconnus, par exemple)
  209.   httrack.norecatch=0;       // ne pas reprendre les fichiers effacÈs par l'utilisateur
  210.   httrack.verbosedisplay=0;  // pas d'animation texte
  211.   strcpybuff(httrack.footer,HTS_DEFAULT_FOOTER);
  212.   httrack.ftp_proxy=1;       // proxy http pour ftp
  213.   strcpybuff(httrack.filelist,"");
  214.   strcpybuff(httrack.lang_iso,"en, *");
  215.   strcpybuff(httrack.mimedefs,"\n"); // aucun filtre mime (\n IMPORTANT)
  216.   //
  217.   httrack.log=stdout;
  218.   httrack.errlog=stderr;
  219.   httrack.flush=1;           // flush sur les fichiers log
  220.   httrack.aff_progress=0;
  221.   httrack.keyboard=0;
  222.   //
  223.   strcpybuff(httrack.path_html,"");
  224.   strcpybuff(httrack.path_log,"");
  225.   strcpybuff(httrack.path_bin,"");
  226.   //
  227.   httrack.maxlink=100000;    // 100,000 liens max par dÈfaut (400Kb)
  228.   httrack.maxfilter=200;     // 200 filtres max par dÈfaut
  229.   httrack.maxcache=1048576*32;  // a peu prËs 32Mo en cache max -- OPTION NON PARAMETRABLE POUR L'INSTANT --
  230.   //httrack.maxcache_anticipate=256;  // maximum de liens ‡ anticiper
  231.   httrack.maxtime=-1;        // temps max en secondes
  232.   httrack.maxrate=-1;        // pas de taux maxi
  233.   httrack.maxconn=10;        // nombre connexions/s
  234.   httrack.waittime=-1;       // wait until.. hh*3600+mm*60+ss
  235.   //
  236.   httrack.exec=argv[0];
  237.   httrack.is_update=0;      // not an update (yet)
  238.   httrack.dir_topindex=0;   // do not built top index (yet)
  239.   //
  240.   httrack.state.stop=0;     // stopper
  241.   //
  242.   _DEBUG_HEAD=0;            // pas de debuggage en tÍtes
  243.   
  244. #if HTS_WIN
  245. #if HTS_ANALYSTE!=2
  246.   {
  247.     int stat;
  248.     wVersionRequested = 0x0101;
  249.     stat = WSAStartup( wVersionRequested, &wsadata );
  250.     if (stat != 0) {
  251.       HTS_PANIC_PRINTF("Winsock not found!\n");
  252.       htsmain_free();
  253.       return -1;
  254.     } else if (LOBYTE(wsadata.wVersion) != 1  && HIBYTE(wsadata.wVersion) != 1) {
  255.       HTS_PANIC_PRINTF("WINSOCK.DLL does not support version 1.1\n");
  256.       WSACleanup();
  257.       htsmain_free();
  258.       return -1;
  259.     }
  260.   }
  261. #endif
  262. #endif
  263.  
  264.   /* Init root dir */
  265.   hts_rootdir(argv[0]);
  266.  
  267. #if HTS_WIN
  268. #else
  269.   /* Terminal is a tty, may ask questions and display funny information */
  270.   if (isatty(1)) {
  271.     httrack.quiet=0;
  272.     httrack.verbosedisplay=1;
  273.   }
  274.   /* Not a tty, no stdin input or funny output! */
  275.   else {
  276.     httrack.quiet=1;
  277.     httrack.verbosedisplay=0;
  278.   }
  279. #endif
  280.  
  281.   /* First test: if -#R then only launch ftp */
  282.   if (argc > 2) {
  283.     if (strcmp(argv[1],"-#R")==0) {
  284.       if (argc==6) {
  285.         lien_back r;
  286.         char* path;
  287.         FILE* fp;
  288.         strcpybuff(r.url_adr,argv[2]);
  289.         strcpybuff(r.url_fil,argv[3]);
  290.         strcpybuff(r.url_sav,argv[4]);
  291.         path=argv[5];
  292.         r.status=1000;
  293.         run_launch_ftp(&r);
  294.         fp=fopen(fconv(path),"wb");
  295.         if (fp) {
  296.           fprintf(fp,"%d %s",r.r.statuscode,r.r.msg);
  297.           fclose(fp); fp=NULL;
  298.           rename(fconv(path),fconcat(path,".ok"));
  299.         } else remove(fconv(path));
  300.       } else {
  301.         printf("htsftp error, wrong parameter number (%d)\n",argc);
  302.       }
  303.       exit(0);   // pas _exit()
  304.     }
  305.   }
  306.  
  307.   // ok, non ftp, continuer
  308.  
  309.  
  310.   // Binary program path?
  311. #ifndef HTS_HTTRACKDIR
  312.   {
  313.     char* path=fslash(argv[0]);
  314.     char* a;
  315.     if ((a=strrchr(path,'/'))) {
  316.       httrack.path_bin[0]='\0';
  317.       strncatbuff(httrack.path_bin,argv[0],(int) a - (int) path);
  318.     }
  319.   }
  320. #else
  321.   strcpybuff(httrack.path_bin, HTS_HTTRACKDIR);
  322. #endif
  323.  
  324.  
  325.   /* filter CR, LF, TAB.. */
  326.   {
  327.     int na;
  328.     for(na=1;na<argc;na++) {
  329.       char* a;
  330.       while( (a=strchr(argv[na],'\x0d')) ) *a=' ';
  331.       while( (a=strchr(argv[na],'\x0a')) ) *a=' ';
  332.       while( (a=strchr(argv[na],9)) )      *a=' ';
  333.       /* equivalent to "empty parameter" */
  334.       if ((strcmp(argv[na],HTS_NOPARAM)==0) || (strcmp(argv[na],HTS_NOPARAM2)==0))        // (none)
  335.         strcpybuff(argv[na],"\"\"");
  336.       if (strncmp(argv[na],"-&",2)==0)
  337.         argv[na][1]='%';
  338.     }
  339.   }
  340.  
  341.  
  342.  
  343.   /* create x_argvblk buffer for transformed command line */
  344.   {
  345.     int current_size=0;
  346.     int size;
  347.     int na;
  348.     for(na=0;na<argc;na++)
  349.       current_size += (strlen(argv[na]) + 1);
  350.     if ((size=fsize("config"))>0)
  351.       current_size += size;
  352.     x_argvblk=(char*) malloct(current_size+32768);
  353.     if (x_argvblk == NULL) {
  354.       HTS_PANIC_PRINTF("Error, not enough memory");
  355.       htsmain_free();
  356.       return -1;
  357.     }
  358.     x_argvblk[0]='\0';
  359.     x_ptr=0;
  360.   }
  361.  
  362.   /* Create new argc/argv, replace alias, count URLs, treat -h, -q, -i */
  363.   {
  364.     char _tmp_argv[2][HTS_CDLMAXSIZE];
  365.     char* tmp_argv[2];
  366.     char tmp_error[HTS_CDLMAXSIZE];
  367.     int tmp_argc;
  368.     int x_argc=0;
  369.     int na;
  370.     tmp_argv[0]=_tmp_argv[0];
  371.     tmp_argv[1]=_tmp_argv[1];
  372.     //
  373.     argv_url=0;       /* pour comptage */
  374.     //
  375.     cmdl_add(argv[0],x_argc,x_argv,x_argvblk,x_ptr);
  376.     na=1;             /* commencer aprËs nom_prg */
  377.     while(na<argc) {
  378.       int result=1;
  379.       tmp_argv[0][0]=tmp_argv[1][0]='\0';
  380.  
  381.       /* VÈrifier argv[] non vide */
  382.       if (strnotempty(argv[na])) {
  383.         
  384.         /* VÈrifier Commande (alias) */
  385.         result=optalias_check(argc,(const char * const *)argv,na,
  386.           &tmp_argc,(char**)tmp_argv,tmp_error);
  387.         if (!result) {
  388.           HTS_PANIC_PRINTF(tmp_error);
  389.           htsmain_free();
  390.           return -1;
  391.         }
  392.         
  393.         /* Copier */
  394.         cmdl_add(tmp_argv[0],x_argc,x_argv,x_argvblk,x_ptr);
  395.         if (tmp_argc > 1) {
  396.           cmdl_add(tmp_argv[1],x_argc,x_argv,x_argvblk,x_ptr);
  397.         }
  398.         
  399.         /* Compter URLs et dÈtecter -i,-q.. */
  400.         if (tmp_argc == 1) {           /* pas -P & co */
  401.           if (!cmdl_opt(tmp_argv[0])) {   /* pas -c0 & co */
  402.             if (argv_url<0) argv_url=0;   // -1==force -> 1=one url already detected, wipe all previous options
  403.             //if (argv_url>=0) {
  404.             argv_url++;
  405.             if (!argv_firsturl)
  406.               argv_firsturl=x_argv[x_argc-1];
  407.             //}
  408.           } else {
  409.             if (strcmp(tmp_argv[0],"-h")==0) {
  410.               help(argv[0],!httrack.quiet);
  411.               htsmain_free();
  412.               return 0;
  413.             } else {
  414.               if (strncmp(tmp_argv[0],"--",2)) {   /* pas */
  415.                 if ((strchr(tmp_argv[0],'q')!=NULL))
  416.                   httrack.quiet=1;    // ne pas poser de questions! (nohup par exemple)
  417.                 if ((strchr(tmp_argv[0],'i')!=NULL)) {  // doit.log!
  418.                   argv_url=-1;        /* forcer */
  419.                   httrack.quiet=1;
  420.                 }
  421.               }
  422.             }
  423.           }
  424.         } else if (tmp_argc == 2) {
  425.           if ((strcmp(tmp_argv[0],"-%L")==0)) {  // liste d'URLs
  426.             if (argv_url<0) argv_url=0;   // -1==force -> 1=one url already detected, wipe all previous options
  427.             //if (argv_url>=0)
  428.             argv_url++;        /* forcer */
  429.           }
  430.         }
  431.       }
  432.  
  433.       na+=result;
  434.     }
  435.     if (argv_url<0)
  436.       argv_url=0;
  437.  
  438.     /* Nouveaux argc et argv */
  439.     argv=x_argv;
  440.     argc=x_argc;
  441.   }
  442.  
  443.  
  444.  
  445.  
  446.   // Ici on ajoute les arguments de config
  447. /*
  448.   if (fexist("config")) {    // configuration        
  449.     x_argvblk2=(char*) calloct(32768,1);
  450.  
  451.     if (x_argvblk2!=NULL) {
  452.       FILE* fp;
  453.       int x_argc2;
  454.           
  455.       //strcpybuff(x_argvblk2,"httrack ");
  456.       fp=fopen("config","rb");
  457.       if (fp) {
  458.         linput(fp,x_argvblk2+strlen(x_argvblk2),32000);
  459.         fclose(fp); fp=NULL;
  460.     
  461.         // calculer arguments selon derniers arguments
  462.         x_argv2[0]=argv[0];
  463.         x_argc2=1;
  464.         {
  465.           char* p=x_argvblk2;
  466.           do {
  467.             x_argv2[x_argc2++]=p;
  468.             p=strchr(p,' ');
  469.             if (p) {
  470.               *p=0;    // octet nul (tableau)
  471.               p++;
  472.             }            
  473.           } while(p!=NULL);
  474.         }
  475.         // recopier arguments actuels (pointeurs uniquement)
  476.         {
  477.          int na;
  478.           for(na=1;na<argc;na++) {
  479.             x_argv2[x_argc2++]=argv[na];
  480.           }
  481.         }
  482.         argc=x_argc2;      // nouvel argc
  483.         argv=x_argv2;      // nouvel argv
  484.       }
  485.     }
  486.   }
  487. */
  488.  
  489.  
  490.   // Option O and includerc
  491.   { 
  492.     int loops=0;
  493.     while (loops<2) {
  494.       char* com;
  495.       int na;
  496.       
  497.       for(na=1;na<argc;na++) {
  498.         
  499.         if (argv[na][0]=='"') {
  500.           char tempo[HTS_CDLMAXSIZE];
  501.           strcpybuff(tempo,argv[na]+1);
  502.           if (tempo[strlen(tempo)-1]!='"') {
  503.             char s[HTS_CDLMAXSIZE];
  504.             sprintf(s,"Missing quote in %s",argv[na]);
  505.             HTS_PANIC_PRINTF(s);
  506.             htsmain_free();
  507.             return -1;
  508.           }
  509.           tempo[strlen(tempo)-1]='\0';
  510.           strcpybuff(argv[na],tempo);
  511.         }
  512.         
  513.         if (cmdl_opt(argv[na])) { // option
  514.           com=argv[na]+1;
  515.           
  516.           while(*com) {
  517.             switch(*com) {
  518.             case 'O':    // output path
  519.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  520.                 HTS_PANIC_PRINTF("Option O needs to be followed by a blank space, and a path (or path,path)");
  521.                 printf("Example: -O /binary/\n");
  522.                 printf("Example: -O /binary/,/log/\n");
  523.                 htsmain_free();
  524.                 return -1;
  525.               } else {
  526.                 char* a;
  527.                 na++;
  528.                 strcpybuff(httrack.path_html,"");
  529.                 strcpybuff(httrack.path_log,"");
  530.                 a=strstr(argv[na],"\",\"");  // rechercher en premier, au cas ou -O "c:\pipo,test","c:\test"
  531.                 if (!a)
  532.                   a=strchr(argv[na],',');  // 2 path
  533.                 else
  534.                   a++;  // position ,
  535.                 if (a) {
  536.                   strncatbuff(httrack.path_html,argv[na],(int) (a-argv[na]));
  537.                   strcatbuff(httrack.path_log,a+1);
  538.                 } else {
  539.                   strcpybuff(httrack.path_log,argv[na]);
  540.                   strcpybuff(httrack.path_html,argv[na]);
  541.                 }
  542.                 // Eliminer les cas comme -O "C:\mirror\"
  543.                 if (httrack.path_log[0]=='"') {  // Guillemets
  544.                   char tmp[256];
  545.                   strcpybuff(tmp,httrack.path_log+1);
  546.                   if (tmp[strlen(tmp)-1]=='"')
  547.                     tmp[strlen(tmp)-1]='\0';
  548.                   strcpybuff(httrack.path_log,tmp);
  549.                 }
  550.                 if (httrack.path_html[0]=='"') {
  551.                   char tmp[256];
  552.                   strcpybuff(tmp,httrack.path_html+1);
  553.                   if (tmp[strlen(tmp)-1]=='"')
  554.                     tmp[strlen(tmp)-1]='\0';
  555.                   strcpybuff(httrack.path_html,tmp);
  556.                 }
  557.                 check_path(httrack.path_log,argv_firsturl);
  558.                 if (check_path(httrack.path_html,argv_firsturl)) {
  559.                   httrack.dir_topindex=1;     // rebuilt top index
  560.                 }
  561.                 
  562.                 //printf("-->%s\n%s\n",httrack.path_html,httrack.path_log);
  563.                 
  564.               }
  565.               break;
  566.             }  // switch
  567.             com++;    
  568.           }  // while
  569.           
  570.         }  // arg
  571.         
  572.       }  // for
  573.      
  574.          /* if doit.log exists, or if new URL(s) defined, 
  575.       then DO NOT load standard config files */
  576.       /* (config files are added in doit.log) */
  577. #if DEBUG_STEPS
  578.       printf("Loading httrackrc/doit.log\n");
  579. #endif
  580.       /* recreate a doit.log (no old doit.log or new URLs (and parameters)) */
  581.       if ((strnotempty(httrack.path_log)) || (strnotempty(httrack.path_html)))
  582.         loops++;      // do not loop once again and do not include rc file (O option exists)
  583.       else {
  584.         if ( (!fexist(fconcat(httrack.path_log,"hts-cache/doit.log"))) || (argv_url>0) ) {
  585.           if (!optinclude_file(fconcat(httrack.path_log,HTS_HTTRACKRC),&argc,argv,x_argvblk,&x_ptr))
  586.             if (!optinclude_file(HTS_HTTRACKRC,&argc,argv,x_argvblk,&x_ptr)) {
  587.               if (!optinclude_file(fconcat(hts_gethome(),"/"HTS_HTTRACKRC),&argc,argv,x_argvblk,&x_ptr)) {
  588. #ifdef HTS_HTTRACKCNF
  589.                 optinclude_file(HTS_HTTRACKCNF,&argc,argv,x_argvblk,&x_ptr);
  590. #endif
  591.               }
  592.             }
  593.         } else
  594.           loops++;      // do not loop once again
  595.       }
  596.  
  597.       loops++;
  598.    } // while
  599.  
  600.   }  // traiter -O
  601.  
  602.   /* load doit.log and insert in current command line */
  603.   if ( fexist(fconcat(httrack.path_log,"hts-cache/doit.log")) && (argv_url<=0) ) {
  604.     FILE* fp=fopen(fconcat(httrack.path_log,"hts-cache/doit.log"),"rb");
  605.     if (fp) {
  606.       int insert_after=1;     /* insÈrer aprËs nom au dÈbut */
  607.       //
  608.       char buff[8192];
  609.       char *p,*lastp;
  610.       linput(fp,buff,8000);
  611.       fclose(fp); fp=NULL;
  612.       p=buff;
  613.       do {
  614.         int insert_after_argc;
  615.         // read next
  616.         lastp=p;
  617.         if (p) {
  618.           p=next_token(p,1);
  619.           if (p) {
  620.             *p=0;    // null
  621.             p++;
  622.           }
  623.         }
  624.  
  625.         /* Insert parameters BUT so that they can be in the same order */
  626.         if (lastp) {
  627.           if (strnotempty(lastp)) {
  628.             insert_after_argc=argc-insert_after;
  629.             cmdl_ins(lastp,insert_after_argc,(argv+insert_after),x_argvblk,x_ptr);
  630.             argc=insert_after_argc+insert_after;
  631.             insert_after++;
  632.           }
  633.         }
  634.       } while(lastp!=NULL);
  635.       //fclose(fp);
  636.     }
  637.   }
  638.  
  639.  
  640.   // Existence d'un cache - pas de new mais un old.. renommer
  641. #if DEBUG_STEPS
  642.   printf("Checking cache\n");
  643. #endif
  644.   if ( (!fexist(fconcat(httrack.path_log,"hts-cache/new.dat"))) || (!fexist(fconcat(httrack.path_log,"hts-cache/new.ndx"))) ) {
  645.     if ( (fexist(fconcat(httrack.path_log,"hts-cache/old.dat"))) && (fexist(fconcat(httrack.path_log,"hts-cache/old.ndx"))) ) {
  646.       remove(fconcat(httrack.path_log,"hts-cache/new.dat"));
  647.       remove(fconcat(httrack.path_log,"hts-cache/new.ndx"));
  648.       //remove(fconcat(httrack.path_log,"hts-cache/new.lst"));
  649.       rename(fconcat(httrack.path_log,"hts-cache/old.dat"),fconcat(httrack.path_log,"hts-cache/new.dat"));
  650.       rename(fconcat(httrack.path_log,"hts-cache/old.ndx"),fconcat(httrack.path_log,"hts-cache/new.ndx"));
  651.       //rename(fconcat(httrack.path_log,"hts-cache/old.lst"),fconcat(httrack.path_log,"hts-cache/new.lst"));
  652.     }
  653.   }
  654.  
  655.   /* Interrupted mirror detected */
  656.   if (!httrack.quiet) {
  657.     if (fexist(fconcat(httrack.path_log,"hts-in_progress.lock"))) {
  658.       /* Old cache */
  659.       if ( (fexist(fconcat(httrack.path_log,"hts-cache/old.dat"))) && (fexist(fconcat(httrack.path_log,"hts-cache/old.ndx"))) ) {
  660.         if (httrack.log != NULL) {
  661.           fprintf(httrack.log,"Warning!\n");
  662.           fprintf(httrack.log,"An aborted mirror has been detected!\nThe current temporary cache is required for any update operation and only contains data downloaded during the last aborted session.\nThe former cache might contain more complete information; if you do not want to lose that information, you have to restore it and delete the current cache.\nThis can easily be done here by erasing the hts-cache/new.* files\n");
  663.           fprintf(httrack.log,"Please restart HTTrack with --continue (-iC1) option to override this message!\n");
  664.         }
  665.         exit(0);
  666.       }
  667.     }
  668.   }
  669.     
  670.   // remplacer "macros" comme --spider
  671.   // permet de lancer httrack sans a avoir ‡ se rappeler de syntaxes comme p0C0I0Qc32 ..
  672. #if DEBUG_STEPS
  673.   printf("Checking last macros\n");
  674. #endif
  675.   {
  676.     int i;
  677.     for(i=0;i<argc;i++) {
  678. #if DEBUG_STEPS
  679.       printf("Checking #%d:\n",argv[i]);
  680.       printf("%s\n",argv[i]);
  681. #endif
  682.       if (argv[i][0]=='-') {
  683.         if (argv[i][1]=='-') {  // --xxx
  684.           if ((strfield2(argv[i]+2,"clean")) || (strfield2(argv[i]+2,"tide"))) {  // nettoyer
  685.             strcpybuff(argv[i]+1,"");
  686.             if (fexist(fconcat(httrack.path_log,"hts-log.txt")))
  687.               remove(fconcat(httrack.path_log,"hts-log.txt"));
  688.             if (fexist(fconcat(httrack.path_log,"hts-err.txt")))
  689.               remove(fconcat(httrack.path_log,"hts-err.txt"));
  690.             if (fexist(fconcat(httrack.path_html,"index.html")))
  691.               remove(fconcat(httrack.path_html,"index.html"));
  692.             if (fexist(fconcat(httrack.path_log,"hts-cache/new.dat")))
  693.               remove(fconcat(httrack.path_log,"hts-cache/new.dat"));
  694.             if (fexist(fconcat(httrack.path_log,"hts-cache/new.ndx")))
  695.               remove(fconcat(httrack.path_log,"hts-cache/new.ndx"));
  696.             if (fexist(fconcat(httrack.path_log,"hts-cache/old.dat")))
  697.               remove(fconcat(httrack.path_log,"hts-cache/old.dat"));
  698.             if (fexist(fconcat(httrack.path_log,"hts-cache/old.ndx")))
  699.               remove(fconcat(httrack.path_log,"hts-cache/old.ndx"));
  700.             if (fexist(fconcat(httrack.path_log,"hts-cache/new.lst")))
  701.               remove(fconcat(httrack.path_log,"hts-cache/new.lst"));
  702.             if (fexist(fconcat(httrack.path_log,"hts-cache/old.lst")))
  703.               remove(fconcat(httrack.path_log,"hts-cache/old.lst"));
  704.             if (fexist(fconcat(httrack.path_log,"hts-cache/new.txt")))
  705.               remove(fconcat(httrack.path_log,"hts-cache/new.txt"));
  706.             if (fexist(fconcat(httrack.path_log,"hts-cache/old.txt")))
  707.               remove(fconcat(httrack.path_log,"hts-cache/old.txt"));
  708.             if (fexist(fconcat(httrack.path_log,"hts-cache/doit.log")))
  709.               remove(fconcat(httrack.path_log,"hts-cache/doit.log"));
  710.             if (fexist(fconcat(httrack.path_log,"hts-in_progress.lock")))
  711.               remove(fconcat(httrack.path_log,"hts-in_progress.lock"));
  712.             rmdir(fconcat(httrack.path_log,"hts-cache"));
  713.             //
  714.           } else if (strfield2(argv[i]+2,"catchurl")) {      // capture d'URL via proxy temporaire!
  715.             argv_url=1;     // forcer a passer les parametres
  716.             strcpybuff(argv[i]+1,"#P");
  717.             //
  718.           } else if (strfield2(argv[i]+2,"updatehttrack")) {
  719. #ifdef _WIN32
  720.             char s[HTS_CDLMAXSIZE];
  721.             sprintf(s,"%s not available in this version",argv[i]);
  722.             HTS_PANIC_PRINTF(s);
  723.             htsmain_free();
  724.             return -1;
  725. #else
  726. #if 0
  727.             char _args[8][256];
  728.             char *args[8];
  729.             
  730.             printf("Cheking for updates...\n");
  731.             strcpybuff(_args[0],argv[0]);
  732.             strcpybuff(_args[1],"--get");
  733.             sprintf(_args[2],HTS_UPDATE_WEBSITE,HTS_PLATFORM,"");
  734.             strcpybuff(_args[3],"--quickinfo");
  735.             args[0]=_args[0];
  736.             args[1]=_args[1];
  737.             args[2]=_args[2];
  738.             args[3]=_args[3];
  739.             args[4]=NULL;
  740.             if (execvp(args[0],args)==-1) {
  741.             }
  742. #endif
  743. #endif
  744.           }
  745.           //
  746.           else {
  747.             char s[HTS_CDLMAXSIZE];
  748.             sprintf(s,"%s not recognized",argv[i]);
  749.             HTS_PANIC_PRINTF(s);
  750.             htsmain_free();
  751.             return -1;
  752.           }
  753.  
  754.         } 
  755.       }
  756.     }
  757.   }
  758.  
  759.   // Compter urls/jokers
  760.   /*
  761.   if (argv_url<=0) { 
  762.     int na;
  763.     argv_url=0;
  764.     for(na=1;na<argc;na++) {
  765.       if ( (strcmp(argv[na],"-P")==0) || (strcmp(argv[na],"-N")==0) || (strcmp(argv[na],"-F")==0) || (strcmp(argv[na],"-O")==0) || (strcmp(argv[na],"-V")==0) ) {
  766.         na++;    // sauter nom de proxy
  767.       } else if (!cmdl_opt(argv[na])) { 
  768.         argv_url++;   // un de plus       
  769.       } else if (strcmp(argv[na],"-h")==0) {
  770.         help(argv[0],!httrack.quiet);
  771.         htsmain_free();
  772.         return 0;
  773.       } else {
  774.         if ((strchr(argv[na],'q')!=NULL))
  775.           httrack.quiet=1;    // ne pas poser de questions! (nohup par exemple)
  776.         if ((strchr(argv[na],'i')!=NULL)) {  // doit.log!
  777.           argv_url=0;
  778.           na=argc;
  779.         }
  780.       }
  781.     }
  782.   }  
  783.   */
  784.  
  785.   // Ici on ajoute les arguments qui ont ÈtÈ appelÈs avant au cas o˘ on rÈcupËre une session
  786.   // Exemple: httrack www.truc.fr -L0 puis ^C puis httrack sans URL : ajouter URL prÈcÈdente
  787.   /*
  788.   if (argv_url==0) {
  789.     //if ((fexist(fconcat(httrack.path_log,"hts-cache/new.dat"))) && (fexist(fconcat(httrack.path_log,"hts-cache/new.ndx")))) {  // il existe dÈja un cache prÈcÈdent.. renommer
  790.     if (fexist(fconcat(httrack.path_log,"hts-cache/doit.log"))) {    // un cache est prÈsent
  791.       
  792.       x_argvblk=(char*) calloct(32768,1);
  793.       
  794.       if (x_argvblk!=NULL) {
  795.         FILE* fp;
  796.         int x_argc;
  797.         
  798.         //strcpybuff(x_argvblk,"httrack ");
  799.         fp=fopen(fconcat(httrack.path_log,"hts-cache/doit.log"),"rb");
  800.         if (fp) {
  801.           linput(fp,x_argvblk+strlen(x_argvblk),8192);
  802.           fclose(fp); fp=NULL;
  803.         }
  804.         
  805.         // calculer arguments selon derniers arguments
  806.         x_argv[0]=argv[0];
  807.         x_argc=1;
  808.         {
  809.           char* p=x_argvblk;
  810.           do {
  811.             x_argv[x_argc++]=p;
  812.             //p=strstr(p," ");
  813.             // exemple de chaine: "echo \"test\"" c:\a "\$0"
  814.             p=next_token(p,1);    // prochain token
  815.             if (p) {
  816.               *p=0;    // octet nul (tableau)
  817.               p++;
  818.             }            
  819.           } while(p!=NULL);
  820.         }
  821.         // recopier arguments actuels (pointeurs uniquement)
  822.         {
  823.           int na;
  824.           for(na=1;na<argc;na++) {
  825.             if (strcmp(argv[na],"-O") != 0)    // SAUF le path!
  826.               x_argv[x_argc++]=argv[na];
  827.             else
  828.               na++;
  829.           }
  830.         }
  831.         argc=x_argc;      // nouvel argc
  832.         argv=x_argv;      // nouvel argv
  833.       }
  834.       
  835.       
  836.     }
  837.     //}
  838.   }
  839.   */
  840.   
  841.   // VÈrifier quiet
  842.   /*
  843.   { 
  844.     int na;    
  845.     for(na=1;na<argc;na++) {
  846.       if (!cmdl_opt(argv[na])) { 
  847.         if ((strcmp(argv[na],"-P")==0) || (strcmp(argv[na],"-N")==0) || (strcmp(argv[na],"-F")==0) || (strcmp(argv[na],"-O")==0) || (strcmp(argv[na],"-V")==0))
  848.           na++;    // sauter nom de proxy
  849.       } else {
  850.         if ((strchr(argv[na],'q')!=NULL) || (strchr(argv[na],'i')!=NULL))
  851.           httrack.quiet=1;    // ne pas poser de questions! (nohup par exemple)
  852.       }
  853.     }
  854.   }
  855.   */
  856.  
  857.   // Pas d'URL
  858. #if DEBUG_STEPS
  859.   printf("Checking URLs\n");
  860. #endif
  861.   if (argv_url==0) {
  862.     // PrÈsence d'un cache, que faire?..
  863.     if ((fexist(fconcat(httrack.path_log,"hts-cache/new.dat"))) && (fexist(fconcat(httrack.path_log,"hts-cache/new.ndx")))) {  // il existe dÈja un cache prÈcÈdent.. renommer
  864.       if (fexist(fconcat(httrack.path_log,"hts-cache/doit.log"))) {    // un cache est prÈsent
  865.         if (x_argvblk!=NULL) {
  866.           int m;        
  867.           // Ètablir mode - mode cache: 1 (cache valide) 2 (cache ‡ vÈrifier)
  868.           if (fexist(fconcat(httrack.path_log,"hts-in_progress.lock"))) {    // cache prioritaire
  869.             m=1;
  870.             recuperer=1;
  871.           } else {
  872.             m=2;
  873.           }
  874.           httrack.cache=m;
  875.           
  876.           if (httrack.quiet==0) {  // sinon on continue automatiquement
  877.             HT_REQUEST_START;
  878.             HT_PRINT("A cache (hts-cache/) has been found in the directory ");
  879.             HT_PRINT(httrack.path_log);
  880.             HT_PRINT(LF);
  881.             if (m==1) {
  882.               HT_PRINT("That means that a transfer has been aborted"LF);
  883.               HT_PRINT("OK to Continue ");
  884.             } else {
  885.               HT_PRINT("That means you can update faster the remote site(s)"LF);
  886.               HT_PRINT("OK to Update ");
  887.             }
  888.             HT_PRINT("httrack "); HT_PRINT(x_argvblk); HT_PRINT("?"LF);
  889.             HT_REQUEST_END;
  890.             if (!ask_continue()) { 
  891.               htsmain_free();
  892.               return 0;
  893.             }
  894.           }
  895.           
  896.         } else {
  897.           HTS_PANIC_PRINTF("Error, not enough memory");
  898.           htsmain_free();
  899.           return -1;
  900.         }
  901.       } else { // log existe pas
  902.         HTS_PANIC_PRINTF("A cache has been found, but no command line");
  903.         printf("Please launch httrack with proper parameters to reuse the cache\n");
  904.         htsmain_free();
  905.         return -1;
  906.       }
  907.       
  908.     } else {    // aucune URL dÈfinie et pas de cache
  909. #if HTS_ANALYSTE!=2
  910.       if (httrack.quiet) {
  911. #endif
  912.         help(argv[0],!httrack.quiet);
  913.         htsmain_free();
  914.         return -1;
  915. #if HTS_ANALYSTE!=2
  916.       } else {
  917.         help_wizard(&httrack);
  918.         htsmain_free();
  919.         return -1;
  920.       }
  921. #endif
  922.       htsmain_free();
  923.       return 0;
  924.     }
  925.   } else {   // plus de 2 paramËtres
  926.     // un fichier log existe?
  927.     if (fexist(fconcat(httrack.path_log,"hts-in_progress.lock"))) {  // fichier lock?
  928.       //char s[32];
  929.       
  930.       httrack.cache=1;    // cache prioritaire
  931.       if (httrack.quiet==0) {
  932.         if ((fexist(fconcat(httrack.path_log,"hts-cache/new.dat"))) && (fexist(fconcat(httrack.path_log,"hts-cache/new.ndx")))) {  // il existe dÈja un cache prÈcÈdent.. renommer
  933.           HT_REQUEST_START;
  934.           HT_PRINT("There is a lock-file in the directory ");
  935.           HT_PRINT(httrack.path_log);
  936.           HT_PRINT(LF"That means that a mirror has not been terminated"LF);
  937.           HT_PRINT("Be sure you call httrack with proper parameters"LF);
  938.           HT_PRINT("(The cache allows you to restart faster the transfer)"LF);
  939.           HT_REQUEST_END;
  940.           if (!ask_continue()) {
  941.             htsmain_free();
  942.             return 0;
  943.           }
  944.         }
  945.       }
  946.     } else if (fexist(fconcat(httrack.path_html,"index.html"))) {
  947.       //char s[32];
  948.       httrack.cache=2;  // cache vient aprËs test de validitÈ
  949.       if (httrack.quiet==0) {
  950.         if ((fexist(fconcat(httrack.path_log,"hts-cache/new.dat"))) && (fexist(fconcat(httrack.path_log,"hts-cache/new.ndx")))) {  // il existe dÈja un cache prÈcÈdent.. renommer
  951.           HT_REQUEST_START;
  952.           HT_PRINT("There is an index.html and a hts-cache folder in the directory ");
  953.           HT_PRINT(httrack.path_log);
  954.           HT_PRINT(LF"A site may have been mirrored here, that could mean that you want to update it"LF);
  955.           HT_PRINT("Be sure parameters are ok"LF);
  956.           HT_REQUEST_END;
  957.           if (!ask_continue()) {
  958.             htsmain_free();
  959.             return 0;
  960.           }
  961.         } else {
  962.           HT_REQUEST_START;
  963.           HT_PRINT("There is an index.html in the directory ");
  964.           HT_PRINT(httrack.path_log);
  965.           HT_PRINT(" but no cache"LF);
  966.           HT_PRINT("There is an index.html in the directory, but no cache"LF);
  967.           HT_PRINT("A site may have been mirrored here, and erased.."LF);
  968.           HT_PRINT("Be sure parameters are ok"LF);
  969.           HT_REQUEST_END;
  970.           if (!ask_continue()) {
  971.             htsmain_free();
  972.             return 0;
  973.           }
  974.         }
  975.       }
  976.     }
  977.   }
  978.   
  979.   
  980.   // Treat parameters
  981.   // Traiter les paramËtres
  982. #if DEBUG_STEPS
  983.   printf("Analyze parameters\n");
  984. #endif
  985.   { 
  986.     char* com;
  987.     int na;
  988.     
  989.     for(na=1;na<argc;na++) {
  990.  
  991.       if (argv[na][0]=='"') {
  992.         char tempo[HTS_CDLMAXSIZE];
  993.         strcpybuff(tempo,argv[na]+1);
  994.         if (tempo[strlen(tempo)-1]!='"') {
  995.           char s[HTS_CDLMAXSIZE];
  996.           sprintf(s,"Missing quote in %s",argv[na]);
  997.           HTS_PANIC_PRINTF(s);
  998.           htsmain_free();
  999.           return -1;
  1000.         }
  1001.         tempo[strlen(tempo)-1]='\0';
  1002.         strcpybuff(argv[na],tempo);
  1003.       }
  1004.  
  1005.       if (cmdl_opt(argv[na])) { // option
  1006.         com=argv[na]+1;
  1007.         
  1008.         while(*com) {
  1009.           switch(*com) {
  1010.           case ' ': case 9: case '-': case '\0': break;
  1011.             //
  1012.           case 'h': 
  1013.             help(argv[0],0); 
  1014.             htsmain_free();
  1015.             return 0;   // dÈja fait normalement
  1016.             //
  1017.           case 'g':    // rÈcupÈrer un (ou plusieurs) fichiers isolÈs
  1018.             httrack.wizard=2;             // le wizard on peut plus s'en passer..
  1019.             //httrack.wizard=0;             // pas de wizard
  1020.             httrack.cache=0;              // ni de cache
  1021.             httrack.makeindex=0;          // ni d'index
  1022.             httrack_logmode=1;            // erreurs ‡ l'Ècran
  1023.             httrack.savename_type=1003;   // mettre dans le rÈpertoire courant
  1024.             httrack.depth=0;              // ne pas explorer la page
  1025.             httrack.accept_cookie=0;      // pas de cookies
  1026.             break;
  1027.           case 'w': httrack.wizard=2;    // wizard 'soft' (ne pose pas de questions)
  1028.             httrack.travel=0;
  1029.             httrack.seeker=1;
  1030.             break;
  1031.           case 'W': httrack.wizard=1;    // Wizard-Help (pose des questions)
  1032.             httrack.travel=0;
  1033.             httrack.seeker=1;
  1034.             break;
  1035.           case 'r':                      // n'est plus le recurse get bestial mais wizard itou!
  1036.             if (isdigit((unsigned char)*(com+1))) {
  1037.               sscanf(com+1,"%d",&httrack.depth);
  1038.               while(isdigit((unsigned char)*(com+1))) com++;
  1039.             } else httrack.depth=3;
  1040.             break;
  1041. /*
  1042.           case 'r': httrack.wizard=0;
  1043.             if (isdigit((unsigned char)*(com+1))) {
  1044.               sscanf(com+1,"%d",&httrack.depth);
  1045.               while(isdigit((unsigned char)*(com+1))) com++;
  1046.             } else httrack.depth=3;
  1047.             break;
  1048. */
  1049.             //
  1050.             // note: les tests httrack.depth sont pour Èviter de faire
  1051.             // un miroir du web (:-O) accidentelement ;-)
  1052.           case 'a': /*if (httrack.depth==9999) httrack.depth=3;*/
  1053.             httrack.travel=0+(httrack.travel&256); break;
  1054.           case 'd': /*if (httrack.depth==9999) httrack.depth=3;*/
  1055.             httrack.travel=1+(httrack.travel&256); break;
  1056.           case 'l': /*if (httrack.depth==9999) httrack.depth=3;*/
  1057.             httrack.travel=2+(httrack.travel&256); break;
  1058.           case 'e': /*if (httrack.depth==9999) httrack.depth=3;*/
  1059.             httrack.travel=7+(httrack.travel&256); break;
  1060.           case 't': httrack.travel|=256; break;
  1061.           case 'n': httrack.nearlink=1; break;
  1062.           case 'x': httrack.external=1; break;
  1063.             //
  1064.           case 'U': httrack.seeker=2; break;
  1065.           case 'D': httrack.seeker=1; break;
  1066.           case 'S': httrack.seeker=0; break;
  1067.           case 'B': httrack.seeker=3; break;
  1068.             //
  1069.           case 'Y': httrack.mirror_first_page=1; break;
  1070.             //
  1071.           case 'q': case 'i': httrack.quiet=1; break;
  1072.             //
  1073.           case 'Q': httrack_logmode=0; break;
  1074.           case 'v': httrack_logmode=1; break;
  1075.           case 'f': httrack_logmode=2; if (*(com+1)=='2') httrack_logmode=3; while(isdigit((unsigned char)*(com+1))) com++; break;
  1076.             //
  1077.           //case 'A': httrack.urlmode=1; break;
  1078.           //case 'R': httrack.urlmode=2; break;
  1079.           case 'K': httrack.urlmode=0; 
  1080.             if (isdigit((unsigned char)*(com+1))) {
  1081.               sscanf(com+1,"%d",&httrack.urlmode);
  1082.               if (httrack.urlmode == 0) {  // in fact K0 ==> K2
  1083.                                            // and K ==> K0
  1084.                 httrack.urlmode=2;
  1085.               }
  1086.               while(isdigit((unsigned char)*(com+1))) com++; 
  1087.             }
  1088.             //if (*(com+1)=='0') { httrack.urlmode=2; com++; } break;
  1089.             //
  1090.           case 'c':
  1091.             if (isdigit((unsigned char)*(com+1))) {
  1092.               sscanf(com+1,"%d",&httrack.maxsoc);
  1093.               while(isdigit((unsigned char)*(com+1))) com++;
  1094.               httrack.maxsoc=max(httrack.maxsoc,1);     // FORCER A 1
  1095.             } else httrack.maxsoc=8;
  1096.             
  1097.             break;
  1098.             //
  1099.           case 'p': sscanf(com+1,"%d",&httrack.getmode); while(isdigit((unsigned char)*(com+1))) com++; break;
  1100.             //        
  1101.           case 'G': sscanf(com+1,LLintP,&httrack.fragment); while(isdigit((unsigned char)*(com+1))) com++; break;
  1102.           case 'M': sscanf(com+1,LLintP,&httrack.maxsite); while(isdigit((unsigned char)*(com+1))) com++; break;
  1103.           case 'm': sscanf(com+1,LLintP,&httrack.maxfile_nonhtml); while(isdigit((unsigned char)*(com+1))) com++; 
  1104.             if (*(com+1)==',') {
  1105.               com++;
  1106.               sscanf(com+1,LLintP,&httrack.maxfile_html); while(isdigit((unsigned char)*(com+1))) com++;
  1107.             } else httrack.maxfile_html=-1;
  1108.             break;
  1109.             //
  1110.           case 'T': sscanf(com+1,"%d",&httrack.timeout); while(isdigit((unsigned char)*(com+1))) com++; break;
  1111.           case 'J': sscanf(com+1,"%d",&httrack.rateout); while(isdigit((unsigned char)*(com+1))) com++; break;
  1112.           case 'R': sscanf(com+1,"%d",&httrack.retry); while(isdigit((unsigned char)*(com+1))) com++; break;
  1113.           case 'E': sscanf(com+1,"%d",&httrack.maxtime); while(isdigit((unsigned char)*(com+1))) com++; break;
  1114.           case 'H': sscanf(com+1,"%d",&httrack.hostcontrol); while(isdigit((unsigned char)*(com+1))) com++; break;
  1115.           case 'A': sscanf(com+1,"%d",&httrack.maxrate); while(isdigit((unsigned char)*(com+1))) com++; break;
  1116.  
  1117.           case 'j': httrack.parsejava=1; if (*(com+1)=='0') { httrack.parsejava=0; com++; } break;
  1118.             //
  1119.           case 'I': httrack.makeindex=1; if (*(com+1)=='0') { httrack.makeindex=0; com++; } break;
  1120.             //
  1121.           case 'X': httrack.delete_old=1; if (*(com+1)=='0') { httrack.delete_old=0; com++; } break;
  1122.             //
  1123.           case 'b': sscanf(com+1,"%d",&httrack.accept_cookie); while(isdigit((unsigned char)*(com+1))) com++; break;
  1124.             //
  1125.           case 'N':
  1126.             if (strcmp(argv[na],"-N")==0) {    // Tout seul
  1127.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {  // erreur
  1128.                 HTS_PANIC_PRINTF("Option N needs a number, or needs to be followed by a blank space, and a string");
  1129.                 printf("Example: -N4\n");
  1130.                 htsmain_free();
  1131.                 return -1;
  1132.               } else {
  1133.                 na++;
  1134.                 if (strlen(argv[na])>=127) {
  1135.                   HTS_PANIC_PRINTF("Userdef structure string too long");
  1136.                   htsmain_free();
  1137.                   return -1;
  1138.                 }
  1139.                 strcpybuff(httrack.savename_userdef,argv[na]);
  1140.                 if (strnotempty(httrack.savename_userdef))
  1141.                   httrack.savename_type = -1;    // userdef!
  1142.                 else
  1143.                   httrack.savename_type = 0;    // -N "" : par dÈfaut
  1144.               }
  1145.             } else {
  1146.               sscanf(com+1,"%d",&httrack.savename_type); while(isdigit((unsigned char)*(com+1))) com++;
  1147.             }
  1148.             break;
  1149.           case 'L': 
  1150.             {
  1151.               sscanf(com+1,"%d",&httrack.savename_83); 
  1152.               switch(httrack.savename_83) {
  1153.               case 0:
  1154.                 httrack.savename_83=1;
  1155.                 break;
  1156.               case 1:
  1157.                 httrack.savename_83=0;
  1158.                 break;
  1159.               default:
  1160.                 httrack.savename_83=2;
  1161.                 break;
  1162.               }
  1163.               while(isdigit((unsigned char)*(com+1))) com++; 
  1164.             }
  1165.             break;
  1166.           case 's': 
  1167.             if (isdigit((unsigned char)*(com+1))) {
  1168.               sscanf(com+1,"%d",&httrack.robots);
  1169.               while(isdigit((unsigned char)*(com+1))) com++;
  1170.             } else httrack.robots=1;
  1171. #if DEBUG_ROBOTS
  1172.             printf("robots.txt mode set to %d\n",httrack.robots);
  1173. #endif
  1174.             break;
  1175.           case 'o': sscanf(com+1,"%d",&httrack.errpage); while(isdigit((unsigned char)*(com+1))) com++; break;
  1176.           case 'u': sscanf(com+1,"%d",&httrack.check_type); while(isdigit((unsigned char)*(com+1))) com++; break;
  1177.             //
  1178.           case 'C': 
  1179.             if (isdigit((unsigned char)*(com+1))) {
  1180.               sscanf(com+1,"%d",&httrack.cache);
  1181.               while(isdigit((unsigned char)*(com+1))) com++;
  1182.             } else httrack.cache=1;
  1183.             break;
  1184.           case 'k': httrack.all_in_cache=1; break;
  1185.             //
  1186.           case 'z': httrack.debug=1; break;  // petit debug
  1187.           case 'Z': httrack.debug=2; break;  // GROS debug
  1188.             //
  1189.           case '&': case '%': {    // deuxiËme jeu d'options
  1190.             com++;
  1191.             switch(*com) {
  1192.             case 'x': httrack.passprivacy=1; if (*(com+1)=='0') { httrack.passprivacy=0; com++; } break;   // No passwords in html files
  1193.             case 'q': httrack.includequery=1; if (*(com+1)=='0') { httrack.includequery=0; com++; } break;   // No passwords in html files
  1194.             case 'I': httrack.kindex=1; if (isdigit((unsigned char)*(com+1))) { sscanf(com+1,"%d",&httrack.kindex); while(isdigit((unsigned char)*(com+1))) com++; }
  1195.               break;    // Keyword Index
  1196.             case 'c': sscanf(com+1,"%d",&httrack.maxconn); while(isdigit((unsigned char)*(com+1))) com++; break;
  1197.             case 'e': sscanf(com+1,"%d",&httrack.extdepth); while(isdigit((unsigned char)*(com+1))) com++; break;
  1198.             case 'B': httrack.tolerant=1; if (*(com+1)=='0') { httrack.tolerant=0; com++; } break;   // HTTP/1.0 notamment
  1199.             case 'h': httrack.http10=1; if (*(com+1)=='0') { httrack.http10=0; com++; } break;   // HTTP/1.0
  1200.             case 'z': httrack.nocompression=1; if (*(com+1)=='0') { httrack.nocompression=0; com++; } break;   // pas de compression
  1201.             case 'f': httrack.ftp_proxy=1; if (*(com+1)=='0') { httrack.ftp_proxy=0; com++; } break;   // proxy http pour ftp
  1202.             case 'P': httrack.parseall=1; if (*(com+1)=='0') { httrack.parseall=0; com++; } break;   // tout parser
  1203.             case 'n': httrack.norecatch=1; if (*(com+1)=='0') { httrack.norecatch=0; com++; } break;   // ne pas reprendre fichiers effacÈs localement
  1204.             case 's': httrack.sizehack=1; if (*(com+1)=='0') { httrack.sizehack=0; com++; } break;   // hack sur content-length
  1205.             case 'v': httrack.verbosedisplay=2; if (isdigit((unsigned char)*(com+1))) { sscanf(com+1,"%d",&httrack.verbosedisplay); while(isdigit((unsigned char)*(com+1))) com++; } break;
  1206.  
  1207.             // preserve: no footer, original links
  1208.             case 'p':
  1209.               httrack.footer[0]='\0';
  1210.               httrack.urlmode=4;
  1211.               break;
  1212.             case 'L':    // URL list
  1213.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1214.                 HTS_PANIC_PRINTF("Option %L needs to be followed by a blank space, and a text filename");
  1215.                 printf("Example: -%%L \"mylist.txt\"\n");
  1216.                 htsmain_free();
  1217.                 return -1;
  1218.               } else{
  1219.                 na++;
  1220.                 if (strlen(argv[na])>=254) {
  1221.                   HTS_PANIC_PRINTF("File list string too long");
  1222.                   htsmain_free();
  1223.                   return -1;
  1224.                 }
  1225.                 strcpybuff(httrack.filelist,argv[na]);
  1226.               }
  1227.               break;
  1228.             case 'S':    // Scan Rules list
  1229.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1230.                 HTS_PANIC_PRINTF("Option %S needs to be followed by a blank space, and a text filename");
  1231.                 printf("Example: -%%S \"myfilterlist.txt\"\n");
  1232.                 htsmain_free();
  1233.                 return -1;
  1234.               } else{
  1235.                 int fz;
  1236.                 na++;
  1237.                 fz = fsize(argv[na]);
  1238.                 if (fz < 0) {
  1239.                   HTS_PANIC_PRINTF("File url list could not be opened");
  1240.                   htsmain_free();
  1241.                   return -1;
  1242.                 } else {
  1243.                   FILE* fp = fopen(argv[na], "rb");
  1244.                   if (fp != NULL) {
  1245.                     int cl = (int) strlen(url);
  1246.                     ensureUrlCapacity(url, url_sz, cl + fz + 8192);
  1247.                     if ((int) fread(url + cl, 1, fz, fp) != fz) {
  1248.                       HTS_PANIC_PRINTF("File url list could not be read");
  1249.                       htsmain_free();
  1250.                       return -1;
  1251.                     }
  1252.                     fclose(fp);
  1253.                     *(url + cl + fz) = '\0';
  1254.                   }
  1255.                 }
  1256.               }
  1257.               break;
  1258.             case 'A':    // assume
  1259.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1260.                 HTS_PANIC_PRINTF("Option %A needs to be followed by a blank space, and a filesystemtype=mimetype/mimesubtype parameters");
  1261.                 printf("Example: -%%A php3=text/html,asp=text/html\n");
  1262.                 htsmain_free();
  1263.                 return -1;
  1264.               } else{
  1265.                 char* a;
  1266.                 na++;
  1267.                 if ( (strlen(argv[na]) + strlen(httrack.mimedefs) + 4) >= sizeof(httrack.mimedefs)) {
  1268.                   HTS_PANIC_PRINTF("Mime definition string too long");
  1269.                   htsmain_free();
  1270.                   return -1;
  1271.                 }
  1272.                 // --assume standard
  1273.                 if (strcmp(argv[na],"standard") == 0) {
  1274.                   strcpybuff(httrack.mimedefs,"\n");
  1275.                   strcatbuff(httrack.mimedefs,HTS_ASSUME_STANDARD);
  1276.                   strcatbuff(httrack.mimedefs,"\n");
  1277.                 } else {
  1278.                   strcatbuff(httrack.mimedefs,argv[na]);
  1279.                   strcatbuff(httrack.mimedefs,"\n");
  1280.                 }
  1281.                 a=httrack.mimedefs;
  1282.                 while(*a) {
  1283.                   switch(*a) {
  1284.                   case ',': case ' ': case '\r': case ';': case '\t':
  1285.                     *a='\n';
  1286.                     break;
  1287.                   }
  1288.                   a++;
  1289.                 }
  1290.               }
  1291.               break;
  1292.               //
  1293.             case 'l': 
  1294.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1295.                 HTS_PANIC_PRINTF("Option %l needs to be followed by a blank space, and an ISO language code");
  1296.                 printf("Example: -%%l \"en\"\n");
  1297.                 htsmain_free();
  1298.                 return -1;
  1299.               } else{
  1300.                 na++;
  1301.                 if (strlen(argv[na])>=62) {
  1302.                   HTS_PANIC_PRINTF("Lang list string too long");
  1303.                   htsmain_free();
  1304.                   return -1;
  1305.                 }
  1306.                 strcpybuff(httrack.lang_iso,argv[na]);
  1307.               }
  1308.               break;
  1309.               //
  1310.             case 'F':     // footer id
  1311.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1312.                 HTS_PANIC_PRINTF("Option %F needs to be followed by a blank space, and a footer string");
  1313.                 printf("Example: -%%F \"<!-- Mirrored from %%s by HTTrack Website Copier/"HTTRACK_AFF_VERSION" "HTTRACK_AFF_AUTHORS", %%s -->\"\n");
  1314.                 htsmain_free();
  1315.                 return -1;
  1316.               } else{
  1317.                 na++;
  1318.                 if (strlen(argv[na])>=254) {
  1319.                   HTS_PANIC_PRINTF("Footer string too long");
  1320.                   htsmain_free();
  1321.                   return -1;
  1322.                 }
  1323.                 strcpybuff(httrack.footer,argv[na]);
  1324.               }
  1325.               break;
  1326.             case 'H':                 // debug headers
  1327.               _DEBUG_HEAD=1;
  1328.               break;
  1329.             case 'O':
  1330. #if HTS_WIN
  1331.               printf("Warning option -%%O has no effect in this system (chroot)\n");
  1332. #else
  1333.               switch_chroot=1;
  1334. #endif
  1335.               break;
  1336.             case 'U':                 // setuid
  1337.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1338.                 HTS_PANIC_PRINTF("Option %U needs to be followed by a blank space, and a username");
  1339.                 printf("Example: -%%U smith\n");
  1340.                 htsmain_free();
  1341.                 return -1;
  1342.               } else {
  1343.                 na++;
  1344. #if HTS_WIN
  1345.                 printf("Warning option -%%U has no effect on this system (setuid)\n");
  1346. #else
  1347. #ifndef HTS_DO_NOT_USE_UID
  1348.                 /* Change the user id and gid */
  1349.                 {
  1350.                   struct passwd* userdef=getpwnam((const char*)argv[na]);
  1351.                   if (userdef) {    /* we'll have to switch the user id */
  1352.                     switch_gid=userdef->pw_gid;
  1353.                     switch_uid=userdef->pw_uid;
  1354.                   }
  1355.                 }
  1356. #else
  1357.                 printf("Warning option -%%U has no effect with this compiled version (setuid)\n");
  1358. #endif
  1359. #endif
  1360.               }
  1361.               break;
  1362.               
  1363.             default: {
  1364.               char s[HTS_CDLMAXSIZE];
  1365.               sprintf(s,"invalid option %%%c\n",*com);
  1366.               HTS_PANIC_PRINTF(s);
  1367.               htsmain_free();
  1368.               return -1;
  1369.                      }
  1370.               break;
  1371.               
  1372.             }
  1373.                     }
  1374.             break;
  1375.             //
  1376.           case '@': {    // troisiËme jeu d'options
  1377.             com++;
  1378.             switch(*com) {
  1379.             case 'i': 
  1380. #if HTS_INET6==0
  1381.               printf("Warning, option @i has no effect (v6 routines not compiled)\n");
  1382. #else 
  1383.               {
  1384.                 int res=0;
  1385.                 if (isdigit((unsigned char)*(com+1))) {
  1386.                   sscanf(com+1,"%d",&res); while(isdigit((unsigned char)*(com+1))) com++; 
  1387.                 }
  1388.                 switch(res) {
  1389.                 case 1:
  1390.                 case 4:
  1391.                   IPV6_resolver=1;
  1392.                   break;
  1393.                 case 2:
  1394.                 case 6:
  1395.                   IPV6_resolver=2;
  1396.                   break;
  1397.                 case 0:
  1398.                   IPV6_resolver=0;
  1399.                   break;
  1400.                 default:
  1401.                   printf("Unknown flag @i%d\n", res);
  1402.                   htsmain_free();
  1403.                   return -1;
  1404.                   break;
  1405.                 }
  1406.               }
  1407. #endif
  1408.               break;
  1409.               
  1410.                 default: {
  1411.                   char s[HTS_CDLMAXSIZE];
  1412.                   sprintf(s,"invalid option %%%c\n",*com);
  1413.                   HTS_PANIC_PRINTF(s);
  1414.                   htsmain_free();
  1415.                   return -1;
  1416.                          }
  1417.                   break;
  1418.                   
  1419.                   //case 's': httrack.sslengine=1; if (isdigit((unsigned char)*(com+1))) { sscanf(com+1,"%d",&httrack.sslengine); while(isdigit((unsigned char)*(com+1))) com++; } break;
  1420.             }
  1421.                     }
  1422.             break;
  1423.             
  1424.             //
  1425.           case '#':  { // non documentÈ
  1426.             com++;
  1427.             switch(*com) {
  1428.             case 'C':   // list cache files : httrack -#C '*spid*.gif' will attempt to find the matching file
  1429.               {
  1430.                 int hasFilter = 0;
  1431.                 int found = 0;
  1432.                 char* filter=NULL;
  1433.                 cache_back cache;
  1434.                 inthash cache_hashtable=inthash_new(HTS_HASH_SIZE);
  1435.                 int backupXFR = htsMemoryFastXfr;
  1436.                 int sendb = 0;
  1437.                 if (isdigit((unsigned char)*(com+1))) {
  1438.                   sscanf(com+1,"%d",&sendb);
  1439.                   while(isdigit((unsigned char)*(com+1))) com++;
  1440.                 } else sendb=0;
  1441.                 if (!((na+1>=argc) || (argv[na+1][0]=='-'))) {
  1442.                   na++;
  1443.                   hasFilter = 1;
  1444.                   filter=argv[na];
  1445.                 }
  1446.                 htsMemoryFastXfr = 1;               /* fast load */
  1447.  
  1448.                 memset(&cache, 0, sizeof(cache_back));
  1449.                 cache.type=1;       // cache?
  1450.                 cache.log=stdout;     // log?
  1451.                 cache.errlog=stderr;  // err log?
  1452.                 cache.ptr_ant=cache.ptr_last=0;   // pointeur pour anticiper
  1453.                 cache.hashtable=(void*)cache_hashtable;      /* copy backcache hash */
  1454.                 cache.ro = 1;          /* read only */
  1455.                 if (cache.hashtable) {
  1456.                   char adr[HTS_URLMAXSIZE*2];
  1457.                   char fil[HTS_URLMAXSIZE*2];
  1458.                   char url[HTS_URLMAXSIZE*2];
  1459.                   char linepos[256];
  1460.                   int  pos;
  1461.                   char* cacheNdx = readfile(fconcat(httrack.path_log,"hts-cache/new.ndx"));
  1462.                   cache_init(&cache,&httrack);            /* load cache */
  1463.                   if (cacheNdx != NULL) {
  1464.                     char firstline[256];
  1465.                     char* a = cacheNdx;
  1466.                     a+=cache_brstr(a, firstline);
  1467.                     a+=cache_brstr(a, firstline);
  1468.                     while ( a != NULL ) {
  1469.                       a=strchr(a+1,'\n');     /* start of line */
  1470.                       if (a) {
  1471.                         htsblk r;
  1472.                         /* */
  1473.                         a++;
  1474.                         /* read "host/file" */
  1475.                         a+=binput(a,adr,HTS_URLMAXSIZE);
  1476.                         a+=binput(a,fil,HTS_URLMAXSIZE);
  1477.                         url[0]='\0';
  1478.                         if (!link_has_authority(adr))
  1479.                           strcatbuff(url, "http://");
  1480.                         strcatbuff(url, adr);
  1481.                         strcatbuff(url, fil);
  1482.                         /* read position */
  1483.                         a+=binput(a,linepos,200);
  1484.                         sscanf(linepos,"%d",&pos);
  1485.                         if (!hasFilter
  1486.                           ||
  1487.                           (strjoker(url, filter, NULL, NULL) != NULL)
  1488.                           ) {
  1489.                           r = cache_read(&httrack, &cache, adr, fil, NULL);    // lire entrÈe cache
  1490.                           if (r.statuscode != -1) {    // No errors
  1491.                             found++;
  1492.                             if (!hasFilter) {
  1493.                               fprintf(stdout, "%s%s%s\r\n", 
  1494.                                 (link_has_authority(adr)) ? "" : "http://", 
  1495.                                 adr, fil);
  1496.                             } else {
  1497.                               char msg[256], cdate[256];
  1498.                               char sav[HTS_URLMAXSIZE*2];
  1499.                               infostatuscode(msg, r.statuscode);
  1500.                               time_gmt_rfc822(cdate);
  1501.  
  1502.                               fprintf(stdout, "HTTP/1.1 %d %s\r\n",
  1503.                                 r.statuscode,
  1504.                                 r.msg[0] ? r.msg : msg
  1505.                                 );
  1506.                               fprintf(stdout, "X-Host: %s\r\n", adr);
  1507.                               fprintf(stdout, "X-File: %s\r\n", fil);
  1508.                               fprintf(stdout, "X-URL: %s%s%s\r\n", 
  1509.                                 (link_has_authority(adr)) ? "" : "http://", 
  1510.                                 adr, fil);
  1511.                               if (url_savename(adr, fil, sav, NULL, NULL, NULL, NULL,
  1512.                                 &httrack, NULL, 0, NULL, 0, &cache, NULL, 0, 0)!=-1) {
  1513.                                 if (fexist(sav)) {
  1514.                                   fprintf(stdout, "Content-location: %s\r\n", sav);
  1515.                                 }
  1516.                               }
  1517.                               fprintf(stdout, "Date: %s\r\n", cdate);
  1518.                               fprintf(stdout, "Server: HTTrack Website Copier/"HTTRACK_VERSION"\r\n");
  1519.                               if (r.lastmodified[0]) {
  1520.                                 fprintf(stdout, "Last-Modified: %s\r\n", r.lastmodified);
  1521.                               }
  1522.                               if (r.etag[0]) {
  1523.                                 fprintf(stdout, "Etag: %s\r\n", r.etag);
  1524.                               }
  1525.                               if (r.totalsize >= 0) {
  1526.                                 fprintf(stdout, "Content-Length: "LLintP"\r\n", r.totalsize);
  1527.                               }
  1528.                               fprintf(stdout, "X-Content-Length: "LLintP"\r\n", (r.size >= 0) ? r.size : (-r.size) );
  1529.                               if (r.contenttype >= 0) {
  1530.                                 fprintf(stdout, "Content-Type: %s\r\n", r.contenttype);
  1531.                               }
  1532.                               if (r.cdispo[0]) {
  1533.                                 fprintf(stdout, "Content-Disposition: %s\r\n", r.cdispo);
  1534.                               }
  1535.                               if (r.contentencoding[0]) {
  1536.                                 fprintf(stdout, "Content-Encoding: %s\r\n", r.contentencoding);
  1537.                               }
  1538.                               if (r.is_chunk) {
  1539.                                 fprintf(stdout, "Transfer-Encoding: chunked\r\n");
  1540.                               }
  1541. #if HTS_USEOPENSSL
  1542.                               if (r.ssl) {
  1543.                                 fprintf(stdout, "X-SSL: yes\r\n");
  1544.                               }
  1545. #endif
  1546.                               if (r.is_write) {
  1547.                                 fprintf(stdout, "X-Direct-To-Disk: yes\r\n");
  1548.                               }
  1549.                               if (r.compressed) {
  1550.                                 fprintf(stdout, "X-Compressed: yes\r\n");
  1551.                               }
  1552.                               if (r.notmodified) {
  1553.                                 fprintf(stdout, "X-Not-Modified: yes\r\n");
  1554.                               }
  1555.                               if (r.is_chunk) {
  1556.                                 fprintf(stdout, "X-Chunked: yes\r\n");
  1557.                               }
  1558.                               fprintf(stdout, "\r\n");
  1559.                               /* Send the body */
  1560.                               if (sendb) {
  1561.                               }
  1562.                             }
  1563.                           }
  1564.                         }
  1565.                       }
  1566.                     }
  1567.                     freet(cacheNdx);
  1568.                   }
  1569.                 }
  1570.                 if (!found) {
  1571.                   fprintf(stderr, "No cache entry found%s%s%s\r\n",
  1572.                     (hasFilter)?" for '":"",
  1573.                     (hasFilter)?filter:"",
  1574.                     (hasFilter)?"'":""
  1575.                     );
  1576.                 }
  1577.                 htsMemoryFastXfr = backupXFR;
  1578.                 return 0;
  1579.               }
  1580.               break;
  1581.             case 'X': htsMemoryFastXfr=1; if (*(com+1)=='0') { htsMemoryFastXfr=0; com++; } break;
  1582.             case '~': /* internal lib test */
  1583.               {
  1584.                 char thisIsATestYouShouldSeeAnError[12];
  1585.                 strcpybuff(thisIsATestYouShouldSeeAnError, "0123456789012345678901234567890123456789");
  1586.                 return 0;
  1587.               }
  1588.               break;
  1589.             case 'f': httrack.flush=1; break;
  1590.             case 'h':
  1591.               printf("HTTrack version "HTTRACK_VERSION"%s\n", WHAT_is_available);
  1592.               return 0;
  1593.               break;
  1594.             case 'p': httrack.aff_progress=1; break;
  1595.             case 'S': httrack.shell=1; break;  // stdin sur un shell
  1596.             case 'K': httrack.keyboard=1; break;  // vÈrifier stdin
  1597.               //
  1598.             case 'L': sscanf(com+1,"%d",&httrack.maxlink); while(isdigit((unsigned char)*(com+1))) com++; break;
  1599.             case 'F': sscanf(com+1,"%d",&httrack.maxfilter); while(isdigit((unsigned char)*(com+1))) com++; break;
  1600.             case 'Z': httrack.makestat=1; break;
  1601.             case 'T': httrack.maketrack=1; break;
  1602.             case 'u': sscanf(com+1,"%d",&httrack.waittime); while(isdigit((unsigned char)*(com+1))) com++; break;
  1603.  
  1604.             case 'R':    // ohh ftp, catch->ftpget
  1605.               HTS_PANIC_PRINTF("Unexpected internal error with -#R command");
  1606.               htsmain_free();
  1607.               return -1;        
  1608.               break;
  1609.             case 'P': {     // catchurl
  1610.               help_catchurl(httrack.path_log);
  1611.               htsmain_free();
  1612.               return 0;
  1613.                       }
  1614.               break;
  1615.           
  1616.             case '0':   /* test #0 : filters */
  1617.               if (na+2>=argc) {
  1618.                 HTS_PANIC_PRINTF("Option #0 needs to be followed by a filter string and a string");
  1619.                 printf("Example: '-#0' '*.gif' 'foo.gif'\n");
  1620.                 htsmain_free();
  1621.                 return -1;
  1622.               } else {
  1623.                 if (strjoker(argv[na+2],argv[na+1],NULL,NULL))
  1624.                   printf("%s does match %s\n",argv[na+2],argv[na+1]);
  1625.                 else
  1626.                   printf("%s does NOT match %s\n",argv[na+2],argv[na+1]);
  1627.                 htsmain_free();
  1628.                 return 0;
  1629.               }
  1630.               break;
  1631.             case '!':
  1632.               if (na+1>=argc) {
  1633.                 HTS_PANIC_PRINTF("Option #! needs to be followed by a commandline");
  1634.                 printf("Example: '-#!' 'echo hello'\n");
  1635.                 htsmain_free();
  1636.                 return -1;
  1637.               } else {
  1638.                 system(argv[na+1]);
  1639.               }
  1640.               break;
  1641.  
  1642.             default: printf("Internal option %c not recognized\n",*com); break;
  1643.             }
  1644.                      }
  1645.             break; 
  1646.           case 'O':    // output path
  1647.             na++;     // sauter, dÈja traitÈ
  1648.             break;
  1649.           case 'P':    // proxy
  1650.             if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1651.               HTS_PANIC_PRINTF("Option P needs to be followed by a blank space, and a proxy proxy:port or user:id@proxy:port");
  1652.               printf("Example: -P proxy.myhost.com:8080\n");
  1653.               htsmain_free();
  1654.               return -1;
  1655.             } else {
  1656.               char* a;
  1657.               na++;
  1658.               httrack.proxy.active=1;
  1659.               // Rechercher MAIS en partant de la fin ‡ cause de user:pass@proxy:port
  1660.               a = argv[na] + strlen(argv[na]) -1;
  1661.               // a=strstr(argv[na],":");  // port
  1662.               while( (a > argv[na]) && (*a != ':') && (*a != '@') ) a--;
  1663.               if (*a == ':') {  // un port est prÈsent, <proxy>:port
  1664.                 sscanf(a+1,"%d",&httrack.proxy.port);
  1665.                 httrack.proxy.name[0]='\0';
  1666.                 strncatbuff(httrack.proxy.name,argv[na],(int) (a - argv[na]));
  1667.               } else {  // <proxy>
  1668.                 httrack.proxy.port=8080;
  1669.                 strcpybuff(httrack.proxy.name,argv[na]);
  1670.               }
  1671.             }
  1672.             break;
  1673.           case 'F':    // user-agent field
  1674.             if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1675.               HTS_PANIC_PRINTF("Option F needs to be followed by a blank space, and a user-agent name");
  1676.               printf("Example: -F \"my_user_agent/1.0\"\n");
  1677.               htsmain_free();
  1678.               return -1;
  1679.             } else{
  1680.               na++;
  1681.               if (strlen(argv[na])>=126) {
  1682.                 HTS_PANIC_PRINTF("User-agent length too long");
  1683.                 htsmain_free();
  1684.                 return -1;
  1685.               }
  1686.               strcpybuff(httrack.user_agent,argv[na]);
  1687.               if (strnotempty(httrack.user_agent))
  1688.                 httrack.user_agent_send=1;
  1689.               else
  1690.                 httrack.user_agent_send=0;    // -F "" dÈsactive l'option
  1691.             }
  1692.             break;
  1693.             //
  1694.           case 'V':    // execute command
  1695.             if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1696.               HTS_PANIC_PRINTF("Option V needs to be followed by a system-command string");
  1697.               printf("Example: -V \"tar uvf some.tar \\$0\"\n");
  1698.               htsmain_free();
  1699.               return -1;
  1700.             } else{
  1701.               na++;
  1702.               if (strlen(argv[na])>=2048) {
  1703.                 HTS_PANIC_PRINTF("System-command length too long");
  1704.                 htsmain_free();
  1705.                 return -1;
  1706.               }
  1707.               strcpybuff(httrack.sys_com,argv[na]);
  1708.               if (strnotempty(httrack.sys_com))
  1709.                 httrack.sys_com_exec=1;
  1710.               else
  1711.                 httrack.sys_com_exec=0;    // -V "" dÈsactive l'option
  1712.             }
  1713.             break;
  1714.             //
  1715.           default: {
  1716.             char s[HTS_CDLMAXSIZE];
  1717.             sprintf(s,"invalid option %c\n",*com);
  1718.             HTS_PANIC_PRINTF(s);
  1719.             htsmain_free();
  1720.             return -1;
  1721.                    }
  1722.             break;
  1723.           }  // switch
  1724.           com++;    
  1725.         }  // while
  1726.         
  1727.       }  else {  // URL/filters
  1728.         char tempo[1024];       
  1729.         if (strnotempty(url)) strcatbuff(url," ");  // espace de sÈparation
  1730.         strcpybuff(tempo,unescape_http_unharm(argv[na],1));
  1731.         escape_spc_url(tempo);
  1732.         strcatbuff(url,tempo);
  1733.       }  // if argv=- etc. 
  1734.       
  1735.     }  // for
  1736.   }
  1737.   
  1738. #if BDEBUG==3  
  1739.   printf("URLs/filters=%s\n",url);
  1740. #endif
  1741.  
  1742. #if DEBUG_STEPS
  1743.   printf("Analyzing parameters done\n");
  1744. #endif
  1745.  
  1746.  
  1747. #if HTS_WIN
  1748. #else
  1749. #ifndef HTS_DO_NOT_USE_UID
  1750.   /* Chroot - xxc */
  1751.   if (switch_chroot) {
  1752.     uid_t userid=getuid();
  1753.     //struct passwd* userdef=getpwuid(userid);
  1754.     //if (userdef) {
  1755.     if (!userid) {
  1756.       //if (strcmp(userdef->pw_name,"root")==0) {
  1757.       char rpath[1024];
  1758.       //printf("html=%s log=%s\n",httrack.path_html,httrack.path_log);    // xxc
  1759.       if ((httrack.path_html[0]) && (httrack.path_log[0])) {
  1760.         char *a=httrack.path_html,*b=httrack.path_log,*c=NULL,*d=NULL;
  1761.         c=a; d=b;
  1762.         while ((*a) && (*a == *b)) {
  1763.           if (*a=='/') { c=a; d=b; }
  1764.           a++;
  1765.           b++;
  1766.         }
  1767.  
  1768.         rpath[0]='\0';
  1769.         if (c != httrack.path_html) {
  1770.           if (httrack.path_html[0]!='/')
  1771.             strcatbuff(rpath,"./");
  1772.           strncatbuff(rpath,httrack.path_html,(int) (c - httrack.path_html));
  1773.         }
  1774.         {
  1775.           char tmp[1024];
  1776.           strcpybuff(tmp,c); strcpybuff(httrack.path_html,tmp);
  1777.           strcpybuff(tmp,d); strcpybuff(httrack.path_log,tmp);
  1778.         }
  1779.       } else {
  1780.         strcpybuff(rpath,"./");
  1781.         strcpybuff(httrack.path_html,"/");
  1782.         strcpybuff(httrack.path_log,"/");
  1783.       }
  1784.       if (rpath[0]) {
  1785.         printf("[changing root path to %s (path_data=%s,path_log=%s)]\n",rpath,httrack.path_html,httrack.path_log);
  1786.         if (chroot(rpath)) {
  1787.           printf("ERROR! Can not chroot to %s!\n",rpath);
  1788.           return -1;
  1789.         }
  1790.         if (chdir("/")) {     /* new root */
  1791.           printf("ERROR! Can not chdir to %s!\n",rpath);
  1792.           return -1;
  1793.         }
  1794.       } else
  1795.         printf("WARNING: chroot not possible with these paths\n");
  1796.     }
  1797.     //}
  1798.   }
  1799.  
  1800.   /* Setuid */
  1801.   if (switch_uid>=0) {
  1802.     printf("[setting user/group to %d/%d]\n",switch_uid,switch_gid);
  1803.     if (setgid(switch_gid))
  1804.       printf("WARNING! Can not setgid to %d!\n",switch_gid);
  1805.     if (setuid(switch_uid))
  1806.       printf("WARNING! Can not setuid to %d!\n",switch_uid);
  1807.   }
  1808.  
  1809.   /* Final check */
  1810.   {
  1811.     uid_t userid=getuid();
  1812.     if (!userid) {              /* running as r00t */
  1813.       printf("WARNING! You are running this program as root!\n");
  1814.       printf("It might be a good idea to use the -%%U option to change the userid:\n");
  1815.       printf("Example: -%%U smith\n\n");
  1816.     }
  1817.   }
  1818. #endif
  1819. #endif
  1820.   
  1821.   //printf("WARNING! This is *only* a beta-release of HTTrack\n");
  1822.   io_flush;
  1823.   
  1824. #if DEBUG_STEPS
  1825.   printf("Cache & log settings\n");
  1826. #endif
  1827.   
  1828.   // on utilise le cache..
  1829.   // en cas de prÈsence des deux versions, garder la version la plus avancÈe,
  1830.   // cad la version contenant le plus de fichiers  
  1831.   if (httrack.cache) {
  1832.     if (fexist(fconcat(httrack.path_log,"hts-in_progress.lock"))) {   // problemes..
  1833.       if (fexist(fconcat(httrack.path_log,"hts-cache/new.dat")) && fexist(fconcat(httrack.path_log,"hts-cache/new.ndx"))) { 
  1834.         if (fexist(fconcat(httrack.path_log,"hts-cache/old.dat")) && fexist(fconcat(httrack.path_log,"hts-cache/old.ndx"))) {
  1835.           // switcher si new<32Ko et old>65Ko (tailles arbitraires) ?
  1836.           // ce cas est peut Ítre une erreur ou un crash d'un miroir ancien, prendre
  1837.           // alors l'ancien cache
  1838.           if (fsize(fconcat(httrack.path_log,"hts-cache/new.dat"))<32768) {
  1839.             if (fsize(fconcat(httrack.path_log,"hts-cache/old.dat"))>65536) {
  1840.               if (fsize(fconcat(httrack.path_log,"hts-cache/old.dat")) > fsize(fconcat(httrack.path_log,"hts-cache/new.dat"))) {
  1841.                 remove(fconcat(httrack.path_log,"hts-cache/new.dat"));
  1842.                 remove(fconcat(httrack.path_log,"hts-cache/new.ndx"));
  1843.                 rename(fconcat(httrack.path_log,"hts-cache/old.dat"),fconcat(httrack.path_log,"hts-cache/new.dat"));
  1844.                 rename(fconcat(httrack.path_log,"hts-cache/old.ndx"),fconcat(httrack.path_log,"hts-cache/new.ndx"));  
  1845.                 //} else {  // ne rien faire
  1846.                 //  remove("hts-cache/old.dat");
  1847.                 //  remove("hts-cache/old.ndx");
  1848.               }
  1849.             }
  1850.           }
  1851.         }
  1852.       }
  1853.     }
  1854.   }
  1855.  
  1856.   // DÈbuggage des en tÍtes
  1857.   if (_DEBUG_HEAD) {
  1858.     ioinfo=fopen(fconcat(httrack.path_log,"hts-ioinfo.txt"),"wb");
  1859.   }
  1860.   
  1861.   {
  1862.     char n_lock[256];
  1863.     // on peut pas avoir un affichage ET un fichier log
  1864.     // ca sera pour la version 2
  1865.     if (httrack_logmode==1) {
  1866.       httrack.log=stdout;
  1867.       httrack.errlog=stderr;
  1868.     } else if (httrack_logmode>=2) {
  1869.       // deux fichiers log
  1870.       structcheck(httrack.path_log);
  1871.       if (fexist(fconcat(httrack.path_log,"hts-log.txt")))
  1872.         remove(fconcat(httrack.path_log,"hts-log.txt"));
  1873.       if (fexist(fconcat(httrack.path_log,"hts-err.txt")))
  1874.         remove(fconcat(httrack.path_log,"hts-err.txt"));
  1875.  
  1876.       httrack.log=fopen(fconcat(httrack.path_log,"hts-log.txt"),"w");
  1877.       if (httrack_logmode==2)
  1878.         httrack.errlog=fopen(fconcat(httrack.path_log,"hts-err.txt"),"w");
  1879.       else
  1880.         httrack.errlog=httrack.log;
  1881.       if (httrack.log==NULL) {
  1882.         char s[HTS_CDLMAXSIZE];
  1883.         sprintf(s,"Unable to create log file %s",fconcat(httrack.path_log,"hts-log.txt"));
  1884.         HTS_PANIC_PRINTF(s);
  1885.         htsmain_free();
  1886.         return -1;
  1887.       } else if (httrack.errlog==NULL) {
  1888.         char s[HTS_CDLMAXSIZE];
  1889.         sprintf(s,"Unable to create log file %s",fconcat(httrack.path_log,"hts-err.txt"));
  1890.         HTS_PANIC_PRINTF(s);
  1891.         htsmain_free();
  1892.         return -1;
  1893.       }
  1894.  
  1895.     } else {
  1896.       httrack.log=NULL;
  1897.       httrack.errlog=NULL;
  1898.     }
  1899.     
  1900.     // un petit lock-file pour indiquer un miroir en cours, ainsi qu'un Èventuel fichier log
  1901.     {
  1902.       FILE* fp=NULL;
  1903.       //int n=0;
  1904.       char t[256];
  1905.       time_local_rfc822(t);    // faut bien que ca serve quelque part l'heure RFC1945 arf'
  1906.       
  1907.       /* readme for information purpose */
  1908.       {
  1909.         FILE* fp=fopen(fconcat(httrack.path_log,"hts-cache/readme.txt"),"wb");
  1910.         if (fp) {
  1911.           fprintf(fp,"What's in this folder?"LF);
  1912.           fprintf(fp,""LF);
  1913.           fprintf(fp,"This folder (hts-cache) has been generated by WinHTTrack "HTTRACK_VERSION"%s"LF, WHAT_is_available);
  1914.           fprintf(fp,"and is used for updating this website."LF);
  1915.           fprintf(fp,"(The HTML website structure is stored here to allow fast updates)"LF""LF);
  1916.           fprintf(fp,"DO NOT delete this folder unless you do not want to update the mirror in the future!!"LF);
  1917.           fprintf(fp,"(you can safely delete old.dat, old.ndx and old.lst files, however)"LF);
  1918.           fprintf(fp,""LF);
  1919.           fprintf(fp,HTS_LOG_SECURITY_WARNING);
  1920.           fclose(fp);
  1921.         }
  1922.       }
  1923.  
  1924.       sprintf(n_lock,fconcat(httrack.path_log,"hts-in_progress.lock"));
  1925.       //sprintf(n_lock,fconcat(httrack.path_log,"hts-in_progress.lock"),n);
  1926.       /*do {
  1927.         if (!n)
  1928.           sprintf(n_lock,fconcat(httrack.path_log,"hts-in_progress.lock"),n);
  1929.         else
  1930.           sprintf(n_lock,fconcat(httrack.path_log,"hts-in_progress%d.lock"),n);
  1931.         n++;
  1932.       } while((fexist(n_lock)) && httrack.quiet);      
  1933.       if (fexist(n_lock)) {
  1934.         if (!recuperer) {
  1935.           remove(n_lock);
  1936.         }
  1937.       }*/
  1938.  
  1939.       // vÈrifier existence de la structure
  1940.       structcheck(httrack.path_html);
  1941.       structcheck(httrack.path_log);
  1942.      
  1943.       // reprise/update
  1944.       if (httrack.cache) {
  1945.         FILE* fp;
  1946.         int i;
  1947. #if HTS_WIN
  1948.         mkdir(fconcat(httrack.path_log,"hts-cache"));
  1949. #else
  1950.         mkdir(fconcat(httrack.path_log,"hts-cache"),HTS_PROTECT_FOLDER);
  1951. #endif
  1952.         fp=fopen(fconcat(httrack.path_log,"hts-cache/doit.log"),"wb");
  1953.         if (fp) {
  1954.           for(i=0+1;i<argc;i++) {
  1955.             if ( ((strchr(argv[i],' ')!=NULL) || (strchr(argv[i],'"')!=NULL) || (strchr(argv[i],'\\')!=NULL)) && (argv[i][0]!='"')  ) {
  1956.               int j;
  1957.               fprintf(fp,"\"");
  1958.               for(j=0;j<(int) strlen(argv[i]);j++) {
  1959.                 if (argv[i][j]==34)
  1960.                   fprintf(fp,"\\\"");
  1961.                 else if (argv[i][j]=='\\')
  1962.                   fprintf(fp,"\\\\");
  1963.                 else
  1964.                   fprintf(fp,"%c",argv[i][j]);
  1965.               }
  1966.               fprintf(fp,"\"");
  1967.             } else if (strnotempty(argv[i])==0) {   // ""
  1968.               fprintf(fp,"\"\"");
  1969.             } else {   // non critique
  1970.               fprintf(fp,"%s",argv[i]);
  1971.             }
  1972.             if (i<argc-1)
  1973.               fprintf(fp," ");
  1974.           }
  1975.           fprintf(fp,LF);
  1976.           fprintf(fp,"File generated automatically on %s, do NOT edit"LF,t);
  1977.           fprintf(fp,LF);
  1978.           fprintf(fp,"To update a mirror, just launch httrack without any parameters"LF);
  1979.           fprintf(fp,"The existing cache will be used (and modified)"LF);
  1980.           fprintf(fp,"To have other options, retype all parameters and launch HTTrack"LF);
  1981.           fprintf(fp,"To continue an interrupted mirror, just launch httrack without any parameters"LF);
  1982.           fprintf(fp,LF);
  1983.           fclose(fp); fp=NULL;
  1984.         //} else if (httrack.debug>1) {
  1985.         //  printf("! FileOpen error, \"%s\"\n",strerror(errno));
  1986.         }
  1987.       }
  1988.       
  1989.       // petit message dans le lock
  1990.       if ( (fp=fopen(n_lock,"wb"))!=NULL) {
  1991.         int i;
  1992.         fprintf(fp,"Mirror in progress since %s .. please wait!"LF,t);
  1993.         for(i=0;i<argc;i++) {
  1994.           if (strchr(argv[i],' ')==NULL)
  1995.             fprintf(fp,"%s ",argv[i]);
  1996.           else    // entre ""
  1997.             fprintf(fp,"\"%s\" ",argv[i]);
  1998.         }
  1999.         fprintf(fp,LF);
  2000.         fprintf(fp, "To pause the engine: create an empty file named 'hts-stop.lock'"LF);
  2001.         fclose(fp); fp=NULL;
  2002.       }
  2003.       
  2004.       // fichier log        
  2005.       if (httrack.log)     {
  2006.         int i;
  2007.         fprintf(httrack.log,"HTTrack"HTTRACK_VERSION"%s launched on %s at %s"LF, 
  2008.           WHAT_is_available,
  2009.           t, url);
  2010.         fprintf(httrack.log,"(");
  2011.         for(i=0;i<argc;i++) {
  2012.           if ((strchr(argv[i],' ')==NULL) || (strchr(argv[i],'\"')))
  2013.             fprintf(httrack.log,"%s ",argv[i]);
  2014.           else    // entre "" (si espace(s) et pas dÈja de ")
  2015.             fprintf(httrack.log,"\"%s\" ",argv[i]);
  2016.         }
  2017.         fprintf(httrack.log,")"LF);
  2018.         fprintf(httrack.log,LF);
  2019.         fprintf(httrack.log,"Information, Warnings and Errors reported for this mirror:"LF);
  2020.         fprintf(httrack.log,HTS_LOG_SECURITY_WARNING );
  2021.         fprintf(httrack.log,LF);
  2022.       }
  2023.  
  2024.       if (httrack_logmode) {
  2025.         printf("Mirror launched on %s by HTTrack Website Copier/"HTTRACK_VERSION"%s "HTTRACK_AFF_AUTHORS""LF,t,WHAT_is_available);
  2026.         if (httrack.wizard==0) {
  2027.           printf("mirroring %s with %d levels, %d sockets,t=%d,s=%d,logm=%d,lnk=%d,mdg=%d\n",url,httrack.depth,httrack.maxsoc,httrack.travel,httrack.seeker,httrack_logmode,httrack.urlmode,httrack.getmode);
  2028.         } else {    // the magic wizard
  2029.           printf("mirroring %s with the wizard help..\n",url);
  2030.         }
  2031.       }
  2032.     }
  2033.     
  2034.     io_flush;
  2035.  
  2036.   /* Info for wrappers */
  2037.   if ( (httrack.debug>0) && (httrack.log!=NULL) ) {
  2038.     fspc(httrack.log,"info"); fprintf(httrack.log,"engine: init"LF);
  2039.   }
  2040. #if HTS_ANALYSTE
  2041.   hts_htmlcheck_init();
  2042. #endif
  2043.  
  2044.   // dÈtourner SIGHUP etc.
  2045. #if HTS_WIN
  2046.   signal( SIGINT  , sig_ask    );   // ^C
  2047.   signal( SIGTERM , sig_finish );   // kill <process>
  2048. #else
  2049.   signal( SIGHUP  , sig_back   );   // close window
  2050.   signal( SIGTSTP , sig_back   );   // ^Z
  2051.   signal( SIGTERM , sig_finish );   // kill <process>
  2052.   signal( SIGINT  , sig_ask    );   // ^C
  2053.   signal( SIGPIPE , sig_brpipe );   // broken pipe (write into non-opened socket)
  2054. /*
  2055. deprecated - see SIGCHLD
  2056. #ifndef HTS_DO_NOT_SIGCLD
  2057.   signal( SIGCLD  , sig_ignore );   // child change status
  2058. #endif
  2059. */
  2060.   signal( SIGCHLD , sig_ignore );   // child change status
  2061. #endif
  2062. #if DEBUG_STEPS
  2063.   printf("Launching the mirror\n");
  2064. #endif
  2065.   
  2066.  
  2067.     // Lancement du miroir
  2068.     // ------------------------------------------------------------
  2069.     if (httpmirror(url, &httrack)==0) {
  2070.       printf("Error during operation (see log file), site has not been successfully mirrored\n");
  2071.     } else {
  2072.       if  (httrack.shell) {
  2073.         HTT_REQUEST_START;
  2074.         HT_PRINT("TRANSFER DONE"LF);
  2075.         HTT_REQUEST_END
  2076.       } else {
  2077.         printf("Done.\n");
  2078.       }
  2079.     }
  2080.     // ------------------------------------------------------------
  2081.  
  2082.     //
  2083.     // Build top index
  2084.     if (httrack.dir_topindex) {
  2085.       char rpath[1024*2];
  2086.       char* a;
  2087.       strcpybuff(rpath,httrack.path_html);
  2088.       if (rpath[0]) {
  2089.         if (rpath[strlen(rpath)-1]=='/')
  2090.           rpath[strlen(rpath)-1]='\0';
  2091.       }
  2092.       a=strrchr(rpath,'/');
  2093.       if (a) {
  2094.         *a='\0';
  2095.         hts_buildtopindex(rpath,httrack.path_bin);
  2096.         if (httrack.log) {
  2097.           fspc(httrack.log,"info"); fprintf(httrack.log,"Top index rebuilt (done)"LF);
  2098.         }
  2099.       }
  2100.     }
  2101.  
  2102.     if (exit_xh ==1) {
  2103.       if (httrack.log) {
  2104.         fprintf(httrack.log,"* * MIRROR ABORTED! * *\nThe current temporary cache is required for any update operation and only contains data downloaded during the present aborted session.\nThe former cache might contain more complete information; if you do not want to lose that information, you have to restore it and delete the current cache.\nThis can easily be done here by erasing the hts-cache/new.* files]\n");
  2105.       }
  2106.     }
  2107.  
  2108.   /* Info for wrappers */
  2109.   if ( (httrack.debug>0) && (httrack.log!=NULL) ) {
  2110.     fspc(httrack.log,"info"); fprintf(httrack.log,"engine: free"LF);
  2111.   }
  2112. #if HTS_ANALYSTE
  2113.   hts_htmlcheck_uninit();
  2114. #endif
  2115.     
  2116.     if (httrack_logmode!=1) {
  2117.       if (httrack.errlog == httrack.log) httrack.errlog=NULL;
  2118.       if (httrack.log) { fclose(httrack.log); httrack.log=NULL; }
  2119.       if (httrack.errlog) { fclose(httrack.errlog); httrack.errlog=NULL; }
  2120.     }  
  2121.     
  2122.     // DÈbuggage des en tÍtes
  2123.     if (_DEBUG_HEAD) {
  2124.       if (ioinfo) {
  2125.         fclose(ioinfo);
  2126.       }
  2127.     }
  2128.     
  2129.     // supprimer lock
  2130.     remove(n_lock);
  2131.   }
  2132.   
  2133.   if (x_argvblk)
  2134.     freet(x_argvblk);
  2135.  
  2136. #if HTS_WIN
  2137. #if HTS_ANALYSTE!=2
  2138. //  WSACleanup();    // ** non en cas de thread tjs prÈsent!..
  2139. #endif
  2140. #endif
  2141. #ifdef HTS_TRACE_MALLOC
  2142.   hts_freeall();
  2143. #endif
  2144.  
  2145.   printf("Thanks for using HTTrack!\n");
  2146.   io_flush;
  2147.   htsmain_free();
  2148.   return 0;    // OK
  2149. }
  2150.  
  2151.  
  2152. // main() subroutines
  2153.  
  2154. // vÈrifier chemin path
  2155. int check_path(char* s,char* defaultname) {
  2156.   int i;
  2157.   int return_value=0;
  2158.  
  2159.   // Replace name: ~/mywebsites/# -> /home/foo/mywebsites/#
  2160.   expand_home(s);
  2161.   for(i=0;i<(int) strlen(s);i++)    // conversion \ -> /
  2162.     if (s[i]=='\\')
  2163.       s[i]='/';
  2164.   
  2165.   // remove ending /
  2166.   if (strnotempty(s))
  2167.   if (s[strlen(s)-1]=='/')
  2168.     s[strlen(s)-1]='\0';
  2169.  
  2170.    // Replace name: /home/foo/mywebsites/# -> /home/foo/mywebsites/wonderfulsite
  2171.   if (strnotempty(s)) {
  2172.     if (s[(i=strlen(s))-1]=='#') {
  2173.       if (strnotempty((defaultname?defaultname:""))) {
  2174.         char tempo[HTS_URLMAXSIZE*2];
  2175.         char* a=strchr(defaultname,'#');      // we never know..
  2176.         if (a) *a='\0';
  2177.         tempo[0]='\0';
  2178.         strncatbuff(tempo,s,i-1);
  2179.         strcatbuff(tempo,defaultname);
  2180.         strcpybuff(s,tempo);
  2181.       } else
  2182.         s[0]='\0';            // Clear path (no name/default url given)
  2183.       return_value=1;     // expanded
  2184.     }
  2185.   }
  2186.  
  2187.   // ending /
  2188.   if (strnotempty(s))
  2189.   if (s[strlen(s)-1]!='/')    // ajouter slash ‡ la fin
  2190.     strcatbuff(s,"/");
  2191.  
  2192.   return return_value;
  2193. }
  2194.  
  2195. // dÈtermine si l'argument est une option
  2196. int cmdl_opt(char* s) {
  2197.   if (s[0]=='-') {  // c'est peut Ítre une option
  2198.     if (strchr(s,'.')!=NULL)
  2199.       return 0;    // sans doute un -www.truc.fr (note: -www n'est pas compris)
  2200.     else if (strchr(s,'/')!=NULL)
  2201.       return 0;    // idem, -*cgi-bin/
  2202.     else if (strchr(s,'*')!=NULL)
  2203.       return 0;    // joker, idem
  2204.     else
  2205.       return 1;
  2206.   } else return 0;
  2207. }
  2208.  
  2209.